我想创建类继承,我的新类创建父类的对象,设置一些默认参数(指向其他对象的指针)。
一开始我有:
btDefaultCollisionConfiguration* collisionConfiguration =
new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
btVector3 worldAabbMin(-1000,-1000,-1000);
btVector3 worldAabbMax(1000,1000,1000);
btAxisSweep3* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax);
colWorld = new btCollisionWorld(dispatcher,broadphase,collisionConfiguration);
colWorld->setDebugDrawer(dbgdraw);
我希望有类似的东西:
colWorld = new myBtCollisionWorld(dbgdraw);
我尝试了很多东西并发明了一个技巧
btVector3 worldAabbMin;
btVector3 worldAabbMax;
class BtOgreCollisionWorld_initializer { //A trick: we need one more constructor to
// initialize default variables; Then we will pass them to btCollisionWorld
// as it stands next in inheritance list
public:
BtOgreCollisionWorld_initializer(btCollisionDispatcher *&dispatcher,
btAxisSweep3 *&broadphase,
btDefaultCollisionConfiguration *&collisionConfiguration)
{
if (!worldAabbMin) worldAabbMin = btVector3(-1000,-1000,-1000);
if (!worldAabbMax) worldAabbMax = btVector3(1000,1000,1000);
if (!collisionConfiguration)
collisionConfiguration = new btDefaultCollisionConfiguration();
if (!dispatcher)
dispatcher = new btCollisionDispatcher(collisionConfiguration);
if (!broadphase) broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax);
};
};
class BtOgreCollisionWorld: public BtOgreCollisionWorld_initializer,
public btCollisionWorld {
public:
//using btCollisionWorld::btCollisionWorld;
BtOgreCollisionWorld(BtOgre::DebugDrawer *dbgdraw,
btCollisionDispatcher* dispatcher = 0, btAxisSweep3* broadphase = 0,
btDefaultCollisionConfiguration* collisionConfiguration = 0)
: BtOgreCollisionWorld_initializer(dispatcher, broadphase,
collisionConfiguration),
btCollisionWorld(dispatcher, broadphase, collisionConfiguration)
{
/*copying variables above*/
this->setDebugDrawer(dbgdraw);
};
protected:
btDefaultCollisionConfiguration* collisionConfiguration;
btCollisionDispatcher* dispatcher;
btVector3 worldAabbMin;
btVector3 worldAabbMax;
btAxisSweep3* broadphase;
};
这背后的想法是"初始化器"首先调用类构造函数并覆盖btCollisionWorld类的变量。
突然间它奏效了。
我理解这似乎是尝试开始一个毫无意义的讨论,但我对c ++并不擅长,并且在搜索它时真的没有找到类似的东西;所以我只是好奇是否有任何可能的陷阱或其他方法来实现这一点。
答案 0 :(得分:2)
看起来太复杂了。从设置一些硬编码值的类继承并不是很好。如果你真的希望派生类在逻辑上是分开的(基于init参数),那么最好对它进行模板化。它将允许您基于不同的初始化参数创建更多此类。
答案 1 :(得分:1)
以下是我的理解(告诉我,如果我错了,我会删除答案):
你的设计看起来很复杂。起初我以为你没有利用继承。但后来我意识到问题应该更复杂。以下是我的理解:
你有一个基类,它有一个依赖于它的环境的构造函数(例如一些外部变量)。我尝试一个更简单的例子:
Dispatcher* dispatcher = new Dispatcher(xyz); // global parameter
class World {
private:
Dispatcher *my_dispatcher; // some private that you can't change later on
public:
World() {
my_dispatcher = dispatcher; // take over the global.
...
}
...
};
然后,您希望派生一个类,其构造函数参数应该影响基类的环境。
class DWorld : public World {
public:
DWorld(Dispatcher* d) : World() {
dispatcher = d; // too late: the base is already created !!!
...
}
...
};
该逻辑在标准中定义:
简而言之:在初始化基础之前,DW世界无法做任何事情!
以下是您的诀窍如何运作:
所以你的诀窍就是使用多重继承。它很聪明!
class Helper {
public:
Helper (Dispatcher* d) {
dispatcher = d;
// do whatever you want to do before World base is intialized
}
};
class DWorld : public Helper, public World {
public:
DWorld(Dispatcher* d) : Helper(d), World() {
... // everything is fine
}
...
};
这并非巧合:这也是在C ++标准中非常精确地定义的:在多重继承的情况下,基本初始化器按照在继承语句中定义它们的顺序运行。所以,首先Helper
然后World
。
然而,您必须处理多重继承,这可能很困难,特别是如果继承树的几个不同层需要相同的帮助器。
另一招:
不幸的是,它在一种情况下工作:你的基础构造函数必须至少有一个参数。
假设我有一个构造函数World(int a
)。在这种情况下,我可以使用辅助函数来避免多重继承:
int helper(Dispatcher*d, int a) {
dispatcher = d;
return a;
}
class DWorld : public World { // single inheritance
public:
DWorld(Dispatcher* d) : World(helper(0)) { } // but function pipeline !
};
这可以使用以下事实:必须首先计算函数才能调用World
构造函数。
具有lambda函数的变体虽然可读性较差,但您甚至可以捕获范围内的任何变量并将其用作最佳拟合:
DWorld(Dispatcher* d) : World([&]()->int {dispatcher = d; return 0; }()) {...}
结论
你有一些工具可以解决你的即时问题。然而,技巧仍然是一个技巧。这是一种解决方法。他最好的解决方案是重新设计基类。