C ++继承类,将修改的参数发送到父构造函数 [英] C++ Inherit class with sending modified parameters to parent's constructor
问题描述
我想创建类继承,其中我的新类创建父类的对象,设置一些默认参数(它们是指向其他对象的指针)。
I want to create class inheritance, where my new class creates object of parent class, setting some default parameters (which are pointers to other objects).
开始我有:
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);
我尝试了很多事情并发明了一个技巧
I tried many things and invented a trick
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类变量。
The idea behind this was that "initializer" class constructor is called first and overwrites the variables for btCollisionWorld class.
突然起作用了。
我明白,它可能似乎是一个无意义的讨论,但我不熟练的c + +,真的没有找到任何类似的,而googled为它;所以我如果有任何可能存在的缺陷或其他方式来实现这个只是好奇。
I understand that it may seem as an attempt to start a pointless discussion, but I'm not skilled at c++ and really haven't found anything like that while googled for it; so I'm just curious if there are any possible pitfalls or other ways to implement this.
推荐答案
这里是什么我明白(告诉我,如果我错了,我会删除答案):
您的设计看起来很复杂。起初我以为你没有利用继承。但后来我意识到问题应该更复杂。这是我的理解:
Your design seems very complicated. At first I thought that you didn't make use of the inheritance. But then I realised that the problem should be more complex. Here is what I understood:
你有一个基类的构造函数,它依赖于它的环境(例如一些外部变量)。我尝试一个更简单的例子:
You have a base class whith a constructor that is dependent on its environment (for example some external variables). I try with a simpler example:
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.
...
}
...
};
然后你想派生一个类,一个构造函数参数应该影响基类的环境。
You then want to derive a class, with a constructor parameter that should affect the environment for the base class.
class DWorld : public World {
public:
DWorld(Dispatcher* d) : World() {
dispatcher = d; // too late: the base is already created !!!
...
}
...
};
此逻辑在标准中定义:
- 基类部分始终在派生类之前构造
- 首先执行基本初始化器(可能初始化base,如果不是默认基础构造器)其他成员,然后才是构造函数的身体指令。
总之:在初始化基础之前,DWorld无法做任何事情!
In short: there is no way the DWorld could do something before initializing the base !
这里是你的招式是如何工作的:
多重继承。它是聪明!
So your trick is to use multiple inheritance. It's clever !
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 ++标准中定义的: ,基本初始值设置按照在继承语句中定义它们的顺序操作。所以这里,首先帮助
然后世界
。
This is not coincidence: this is also defined very precisely in the C++ standard: in case of multiple inheritance, the base initializers operate in the order in which you defined them in the inheritance statement. So here, first Helper
then World
.
然而,你必须处理多重继承,这可能很困难,尤其是如果在继承树的几个不同层需要相同的助手。
However you then have to deal with multiple inheritance, which can be difficult, especially if the same helper is needed at several different layers of the inheritance tree.
现在又一个窍门:
Now another trick:
不幸的是,基本构造函数必须至少包含一个参数。
Unfortunately, it works under one condition: your base constructor must take at least one parameter.
假设我有一个构造函数World( int a
)。在这种情况下,我可以避免多重继承的帮助函数:
Suppose I had a constructor World(int a
). In this case I could a helper function avoiding multiple inheritance:
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
构造函数。
This works using the fact that the function must be evaluated first in order to call the World
constructor.
具有lambda函数的变体虽然不太可读,但允许您捕获范围内的任何变量,并将其用作最佳拟合:
The variant with lambda functions, although less readable, permits you even to capture any variables in scope and use them as best fits:
DWorld(Dispatcher* d) : World([&]()->int {dispatcher = d; return 0; }()) {...}
结论
你在这里有一些工具来解决你的immedite问题。然而,一个伎俩仍然是一个伎俩。这是一个解决方法。他最好的解决方案是重新设计基类。
You have here some tools to solve your immedite problem. However a trick remains a trick. It's a workaround. he best solution would be to redesign the base class.
这篇关于C ++继承类,将修改的参数发送到父构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!