re: 硕士论文致谢 Kevin Lynx 2010-04-29 16:37
好吧。原来你也认识潘李亮。。。
re: [转载]低耦合模块间的通信组件:两个模板 Kevin Lynx 2010-04-21 16:31
不明真相地路过。。。
re: 毕业设计截图(计算机图形学) Kevin Lynx 2010-04-20 09:55
- -#
博客后台管理:文件->上传即可
re: [总结]中间/目标代码生成 Kevin Lynx 2010-04-10 17:04
@陈梓瀚(vczh)
我当时想试试直接生成代码的感觉,因为看到lua就是这样做的。:D。所以就折腾了下自己。
PS,美帝不错吧。
re: 讨论:单件模式的优点何在?有无存在的必要? Kevin Lynx 2010-03-29 13:37
@溪流
这个问题某种角度来看,就如同对成员变量不管应用情景如何都提供Get/Set一样,同public一样了。
我觉得唯一的区别,还是一种安全控制吧:
class Singleton
{
public:
static Singleton &GetInstance() { static Singleton ob; .... }
private:
Singleton() { ... }
Singleton( const Singleton & ) ...
};
那么,这个Singleton对象就只存在一份。
当然,也有单件不作constructor的private限制的。
re: lua和python谁更适用于嵌入MMORPG? Kevin Lynx 2010-03-22 20:48
@aydge
lua里的线程并非OS里的线程。大家都知道的WOW里的LUA,用于其客户端的UI扩展制作。本文提到的应用主要集中于服务器端的逻辑扩展,如任务、剧情等。
没想到这种东西有这么现成的。我们还是自己写的崩溃捕获。可以根据pdb文件dump出崩溃时刻的调用堆栈之类的。收藏了。
对这种支持多种字符串资源的问题,没必要自己写个程序去生成对应的代码文件吧?
english_res.txt:
IDS_TYPE_ERROR "XXXXX%s"
const char *s = LoadString( IDS_TYPE_ERROR );
sprintf( buf, s, err );
re: 简要实现正则表达式匹配字符串[未登录] kevin lynx 2010-02-20 19:34
@feizai
是啊。
re: 需要判断指针为空吗[未登录] kevin lynx 2010-02-11 10:49
这个问题在我们组里也备受争议。有人觉得对每个指针进行拿捏然后再决定判断,很多余,所以索性对所有指针进行空判断;有人觉得没必要写那么多冗余代码,需要对每个指针进行上下文审查。
拿一个接口为例,接口实现里是否有必要对参数进行判断?接口调用者是否需要对返回值做判断?反正这种事情挺纠结的.
re: 静态库中全局变量的初始化问题 Kevin Lynx 2010-02-10 16:43
@金庆
@李现民
3q for your comments.
今天随便看了个文档
http://linux.chinaunix.net/bbs/thread-910296-1-1.html,<Linker Algorithm.pdf>恰好在里面看到和我这里提到的相同的2点结论
re: WOF(名将三国)的TGL文件格式 Kevin Lynx 2010-01-26 08:53
@饭中淹
- -
诡异。。我还以为你发漏了。我还用OD反汇编查找了下字符串。
re: WOF(名将三国)的TGL文件格式 Kevin Lynx 2010-01-25 14:28
占位置。学下破解思路。
PS,你那个工具怎么用?貌似需要将TGL文件放在同目录且改名为stand_1.tgl ?
re: 静态库中全局变量的初始化问题 Kevin Lynx 2010-01-20 09:14
@OwnWaterloo
一样的。
re: 静态库中全局变量的初始化问题 Kevin Lynx 2010-01-18 08:52
@OwnWaterloo
这个机会是什么意思?
re: 静态库中全局变量的初始化问题 Kevin Lynx 2010-01-17 23:00
@OwnWaterloo
@LOGOS
加extern是什么意思?文章中的例子,只是因为链接器没有为静态库中的全局对象生成初始化代码。我也并不关心每一个local的初始化顺序,因为他们是全局的,所以他们肯定会先于main被初始化。整个文章的意思,其实是说,链接器并没有生成这个自动初始化的代码,因为链接器觉得这几个“没有”被使用的全局对象不需要,所以就没生成。
围观悲剧的楼主。。。语言设置问题。可能是你设置被reset了
re: 2005-2009年个人总结 Kevin Lynx 2009-12-24 09:11
怎么像临终感言。。。
re: 很傻很天真之Array Kevin Lynx 2009-10-12 09:19
- -|
重载逗号运算符,不会改变函数中逗号的语义。 - -!
是用于改变逗号表达式中逗号的语义,如:
ArrayDimension a;
a, 1; //逗号表达式
标准的逗号表达式其实还应该有个返回值。如:
class Test
{
public:
Test( int i ) : index( i )
{
}
const Test &operator, ( const Test &other )
{
return *this;
}
private:
int index;
};
Test a( 1 ), b( 2 ), c( 3 );
c = a, b;
不懂C#里的动态多维数组,所以对你这里的需求不作评论。:)
如果要支持不定个数的参数,要么使用C里的...(如printf),要么重载很多版本,即使模板也无法解决这个问题。如果太懒不想写那么多重载版本,可以考虑用宏自动生成这些代码。
re: HGE核心函数注释 Kevin Lynx 2009-09-20 15:23
应该去分析下graphics.cpp下的图形渲染部分。
re: 怀念 —— 与大牛一起度过的日志[未登录] Kevin Lynx 2009-09-03 14:04
大致浏览了你BLOG的所有文章,鼓励下你。加油。
re: 使用std::vector 的陷阱[未登录] Kevin Lynx 2009-09-03 13:37
其实我觉得这不是vector给你设的“陷阱”,STL容器只有责任维护你给他的东西,但没理由维护这个东西里面的东西。不仅仅是vector,STL所有的容器如果按你这种思维去用,都会出问题:
class Test
{
int *a;
~Test()
{
delete a;
}
};
std::vector<Test> 维护Test::a其实应该是你的责任。
re: 怕了开源跨平台的东东了[未登录] Kevin Lynx 2009-09-03 13:32
刚开始肯定会不习惯。很多开源项目会依赖第三方库,但是下载下来的包里一般都不带第三方库。得自己去找,还得保证版本一致。习惯就好了,总比让你重头自己写个UI库好吧。:)
re: 低耦合模块间的通信组件:两个模板 Kevin Lynx 2009-08-23 16:13
@OwnWaterloo
其实工作量这事,本来也就没有被减少。就工作量(代码量)这个角度来比较两者的话。OnE1 OnE2和OnEvent(以后讨论就说前者后者)比较而言,在增加新的事件通知时,前者需要增加通信层接口声明(也就是那个被UI继承的基类);后者需要从Param逐个取数据,前者是直接在参数里,如果前者也使用Param或者tuple来组织参数,也免不了解参数。
我觉得后者较前者让人爽的好处就是:永远不需要改这个中间通信层。
说下我现在是怎么派发通知的,这个其实也被放在这个通信中间层:
class OpNotify
{
typedef void (*HandleNotifyFnT)( any *data );
public:
AddNotifyHandler( long event_id, HandleNotifyFnT fn );
void Notify( long event_id, any data );
private:
std::map<long, HandleNotifyFnT> handleFuncTable;
};
UI层需要注册处理事件通知的函数到handleFuncTable里。逻辑层每次派发事件通知时,调用OpNotify::Notify,这个函数简单地从handleFuncTable里找对应的处理函数。
这个样子之后,避开了switch...case。谁都知道,随着事件类型的增加,switch...case也将急速膨胀。进一步地,通信中间层永远不需要修改了。
现在逻辑层派发事件通知时:
OP_NOTIFY( NT_ENTER_RGN, any( create_param( player, rgn_id ) ) );
// OP_NOTIFY被定义为OpNotify::Notify
UI层只需要定义NT_ENTER_RGN的处理函数,并注册到OpNotify,该处理函数大致为:
void HandleEnterRgn( any *data )
{
typedef Param2<Player, long> ParamType;
ParamType *p = any_cast<ParamType>( data );
Player *player = p->p1;
long rgn_id = p->p2;
}
re: 低耦合模块间的通信组件:两个模板 Kevin Lynx 2009-08-23 15:31
@OwnWaterloo
是啊。严格来说,不算降低耦合。因为UI和逻辑层确实得协商设置哪些通知事件。不过,反正这个逻辑模块本身就是要通知UI事件触发的。这样做之后,逻辑模块不需要管UI是否处理,只需要通知。在任何地方想怎样通知就通知。整个程序换了UI后,逻辑层也不需要改,只改UI的通知处理即可。
另一方面,如果使用
void OnE1(tuple<e11,...> );
void OnE2(tuple<e21,...> );
void OnE3(tuple<e31,...> );
这种方式,就会涉及到添加很多通知接口。这个负责通信的中间层就会越来越庞大。虽然,OnEvent(int e, any );这个方式会导致添加越来越多的事件类型定义,但总比添加一个OnEn好吧?:)
很少做这种UI比较复杂的应用程序,不知道其他人有没有好的模块架构方法。实在不想把UI和逻辑揉得那么紧。看过一些人直接在MFC的OnXXX里写一堆逻辑代码就觉得受不了。 我现在做的东西里就包含MFC和控制台两套UI,甚至在GUI方面差点换到bcb。
re: 低耦合模块间的通信组件:两个模板 Kevin Lynx 2009-08-23 13:38
@OwnWaterloo
对,就是你说的这个意思。我也记得有个tuple这个东西。但是我一般不用boost,太大,太多。可以用来学习。:)
re: 指针和模块健壮 Kevin Lynx 2009-08-18 11:54
@lin
当时那个BUG是因为C++代码中对某个指针没判断,而由于某些临界条件就会导致这个指针为NULL。恰好可以通过在策划的脚本里做些修改而避免程序里那段代码的执行。这个跟具体的应用环境有关系,别误会。
re: 强大的bcb Kevin Lynx 2009-08-15 14:02
@OwnWaterloo
3Q
@艹
你就解释下我遇到的那些“BUG”是怎么回事就行了,就事论事。或者你可以告诉我,new std::ofstream在你的BCB上没问题。你的程序编译时不会出现F1004 Internal compiler error。
re: 用脚本实现副本 Kevin Lynx 2009-07-16 22:10
应该不是“用脚本实现副本”,我觉得应该是提供脚本接口给策划来创建副本。副本在很大程度上还是按照一般场景被服务器管理。
re: 实现functor - 增强型的函数指针 Kevin Lynx 2009-07-08 10:30
@deadlm
- -|
re: 实现functor - 增强型的函数指针 Kevin Lynx 2009-07-05 22:40
@deadlm
没用过pascal,不同语言带来的感受肯定不同。:)
functor之类的东西,为了支持各种不同类型的函数,其内部实现确实很恶心,而且少不了复制代码。后来发现有宏递归这种东西(
http://www.cppblog.com/kevinlynx/archive/2008/08/20/59451.html boost中甚至直接有个macro库),虽然内部实现可以少写些代码(用宏来帮助生成),但是其代码看起来更纠结。:D
re: 实现functor - 增强型的函数指针 Kevin Lynx 2009-07-05 16:50
@deadlm
functor这种东西本质上确实如你所说是保存一个“函数”指针。其实偏要加上返回值类型以及各个参数的类型,我觉得主要还是哄好编译器。
void func( int );
void func( int, char );
这两个函数在语言层次毕竟属于不同的类型,functor在回调他们时,需要知道传多少个参数。这些信息都需要保存起来。
template在整个C++中完全属于一种花哨的东西,当然不可否认其作用,如果实在烦这些,可以无视这些语言特性。
之所以我不敢“蔑视”STL、LOKI之类的库,是因为我自认能力没到这级别。也许以后我可以。
class lua_binder<R ( P1 )> 是lua_binder的偏特化,因为lua_binder本体只有一个类型参数,所以,不能写:
class lua_binder<R, P1>。这么说来,在支持多参数函数的情况下,要么使用functor<int, TYPE_LIST1( ...的形式,要么使用functor<int (int)>的形式。对于functor<int, int>的形式,你指的是怎样的实现?(很久没在弄模板这些东西,有点生疏)。
re: 实现functor - 增强型的函数指针 Kevin Lynx 2009-07-04 17:56
@deadlm
并不见得functor<void, int, char>就比function< void, TYPE_LIST2( int, char )>好。
functor<void, int, char>是需要诸如:
template <typename R, typename P1>
class lua_binder<R ( P1 )>
的语法支持。而并不见得所有的编译器都支持。另外,我没有提供这样的接口也并不见得我写不出来:
http://www.cppblog.com/kevinlynx/archive/2008/08/20/59451.html
http://www.cppblog.com/kevinlynx/archive/2008/08/13/58684.html
另外,这里的TYPE_LIST机制取自于loki库。佩服哥们有蔑视loki库的魄力。
re: 基类角色之对象管理器 Kevin Lynx 2009-07-02 17:24
虽然不是很明白饭中淹关于LINK对象的意思,但是我获得了灵感,写了下面的代码:
///
///
///
#include <stdio.h>
#include <list>
class ref_op
{
public:
virtual void be_null() { }
};
typedef std::list<ref_op*> RefOpList;
class ref_base
{
public:
~ref_base()
{
clear_ops();
}
void add_ref( ref_op *op )
{
_oplist.push_back( op );
}
void clear_ops()
{
for( RefOpList::const_iterator it = _oplist.begin();
it != _oplist.end(); ++ it )
{
(*it)->be_null();
}
}
private:
RefOpList _oplist;
};
template <typename _Tp>
class auto_null : public ref_op
{
public:
void fetch( _Tp *t )
{
_t = t;
t->add_ref( this );
}
auto_null<_Tp> &operator = ( _Tp *t )
{
fetch( t );
return *this;
}
void be_null()
{
_t = 0;
}
operator _Tp*()
{
return _t;
}
private:
_Tp *_t;
};
//////////////////////////////////////////////////////////////////////////////
class CMonster : public ref_base
{
};
class CMonsterAI
{
public:
void SetOwner( CMonster *pOwner )
{
m_Owner = pOwner;
}
void Test()
{
if( (CMonster*)m_Owner == NULL )
{
printf( "The owner is null.\n" );
}
else
{
printf( "The owner is NOT null.\n" );
}
}
private:
auto_null<CMonster> m_Owner;
};
int main()
{
CMonster *pMonster = new CMonster();
CMonsterAI *pAI = new CMonsterAI();
pAI->SetOwner( pMonster );
pAI->Test();
delete pMonster;
pAI->Test();
delete pAI;
return 0;
}
CMonster内部会保存一个CMonster的指针,当CMonster被删除掉时,会自动更新CMonsterAI内部的CMonster“指针”为NULL。接口比较简单:1)在会被引用(即被其他对象保存其指针)的类设计中派生(或组合)ref_base类,ref_base类简单来说就是保存一个引用类对象列表,通过基类ref_op可以使得ref_base保存不同类型的引用类(例如CMonsterAI可以保存CMonster, CRegion也可以保存CMonster),ref_base在析构时自动回调引用类对象的be_null函数,be_null函数在auto_null类中自动把CMonster*设置为NULL。
通过重载operator=,使得SetOwner函数里不需要做其他操作(看起来)。
re: 基类角色之对象管理器 Kevin Lynx 2009-07-02 14:10
本质上就是通过让其他模块不保存这个object的直接指针,而是一个ID,然后通过一个manager由这个ID而获取到这个object*,是可以有效减少指针无效的问题。但是,面对的最大问题就在于这个查找过程。你这里用的是std::map,我们用的是stdext::hash_map,我自己都觉得有点速度问题。希望能在这个问题上找到良好的解决办法。:)
re: USACO 3.1 Stamps Kevin Lynx 2009-07-01 08:55
不要再在首页发布这些东西了。基本上只有代码,不知道发首页的目的是什么。我的RSS READER订阅了CPPBLOG首页,但全是你的东西。
这个测试例子确实有问题。把一个对象(shared_ptr)和一个指针(string*)分别作为map的key,对象肯定会比指针慢。对象用于map的key会涉及到很多复制操作。
@owlcn
应该不支持重入。因为都是对同一个lua_State操作。
re: GDI+中从内存读取图片/保存图片到内存 Kevin Lynx 2009-06-20 10:58
@mike7734@sina.com
你最好找人发一份c++ primer给你。:)
@adie
刚正在看vc2005中的xtree找原因。在_Lbound中,确实是因为_DEBUG_LT_PRED导致DEBUG和RELEASE使用了不同的代码。而且确实是因为_Lbound是const的才导致this->comp也是const的。但是,在看到你评论之前我还没反应过来:因为this->comp通过作为函数参数而去掉了const修饰,囧。
起码真相大白了。3Q
@adie
1.我这里说的predicator,指的是less本身。包括传给find_if的functor,都被我称为predicator。STL内部保存这种predicator,都是以value的形式保存。既然是value的形式,就不会存在调用这个predicator的operator()必须要求其为bool (*)() const类型的。以前没搞清楚这个问题,现在也没关注过。
你举的例子中,谈的是这个predicator的bool operator()( ...)成员函数的参数为const&。对于less而言,它的这个operator()的参数是map内部保存的element。无论是从效率还是其他方面,是肯定要const&的。
2.初始化顺序这个问题,我对链接器细节没怎么关注过。不过,情况可能真如你所说。谢过。
re: 实现一种解释性脚本语言(一) Kevin Lynx 2009-05-23 17:05
@AJkm
是的。:)
@小马
为什么你不打开libevent的源代码搜索下evbuffer呢??
@小马
在我印象里,evbuffer用于缓存逻辑层(即l基于libevent那一层)将要发送的数据,以及缓存从设备(fd)里读取出的数据。
re: VS 2010 C++ 王者归来 Kevin Lynx 2009-04-28 13:46
个人从来没有认为C/C++就是穷途末路。技术环境在浮躁,也不至于认为某个语言不行了。
C++0x的新特性看起来还比较有趣。
re: 终于买到了《Unix编程艺术》[未登录] Kevin Lynx 2009-04-08 17:12
灌水,支持<unix编程艺术>
@happyday
代码确实粘贴错误,谢谢提醒。
@无名
图确实存在问题,谢谢提醒。
文章已做过微小修改。
re: 自己实现memcached客户端库[未登录] Kevin Lynx 2009-03-26 18:05
@阿斯蒂芬
能不能具体点?哪个文件,哪一行?
我稍微搜索了下代码,发现只有在fun_test.txt里才有sizeof( addr ),这个文件是用于功能测试的,只要kl_memcached下的源文件编译得过你就可以使用。:)