最近想用做一种C++ Script,来分离引擎和游戏,AI就可以完全用这种C++ Script来做,不需要牵涉到任何引擎的代码,只是使用引擎暴露的API,这样做的好处很多,最重要的就是可以只依赖于API,减少了高层逻辑和底层引擎的耦合,当然,这样的结构就需要引擎提供一套完备的API接口。在接口中,由于是还是使用C++,对内存操作的接口就不可避免,因此就引出了我今天想说的这个话题。
对这个接口我们有几个要求,首先,不使用new操作符(虽然可以重载new或者placement new,但我们希望我们的API接口格式统一,比如都用函数,或类),还有提供和new一样的完备操作。我一开始写了个最简单的做法:
template<typename T>
T* MEM_New()
{
return new T;
}
对于类Test,在C++Script里可以这样使用这个接口:
Test *pT = MEM_New<Test>();
但这样做有一个最大的问题,就是在C++Script里的类只能用默认构造函数生成实例了,这显然限制了高层的代码,会用起来很不爽(当然,你也可以和GPP程序员说,你只能这么用)。要没限制的话,第一个想到的,就是用宏:
#define MEM_New(ctor) new ctor
Test *pT = MEM_New(Test());
这样的的做法,可以解决问题,不过,这和直接提供new没什么区别了,不符合设计思想,最近在看Reflection的相关实现,受到启发,我想到了一种方式,可以比较完美的解决这个问题,还是回到模板的思路上来:
template<typename T>
T* MEM_New()
{
return new T;
}template<typename T, typename P1>
T* MEM_New(const P1& p1)
{
return new T(p1);
}template<typename T, typename P1, typename P2>
T* MEM_New(const P1& p1, const P2& p2)
{
return new T(p1, p2);
}
这里我写了无参数,一个参数,两个参数的MEM_New版本,可以支持,0个到2个参数的构造函数形式,可以照着这个写法写出支持任意多个参数的API版本,一般写到10个以上就够用了,没人会写超过10个参数的构造函数吧。
当然,在Script里使用起来也很简单,假设我们的Test类有三个构造函数,一个是没参数的,一个是带一个int,还有一个是带一个int,一个const char*,在C++Script里就是这样:
Test *pT0 = MEM_New<Test>();
Test *pT1 = MEM_New<Test>(7);
Test *pT0 = MEM_New<Test>(8, “Hello”);
我觉得,挺完美,欢迎留言讨论。
————————————————————————
作者:Finney
Blog:AI分享站(http://www.aisharing.com/)
Email:finneytang@gmail.com
本文欢迎转载和引用,请保留本说明并注明出处
————————————————————————
现在的话,应该可以用变长模板来实现了
这篇有年头了,我也许久不用c++了
用boost pp加模板能更美,不信你试试
还没用惯boost,太复杂