C ++继承类,将修改的参数发送到父构造函数 [英] C++ Inherit class with sending modified parameters to parent's constructor

查看:212
本文介绍了C ++继承类,将修改的参数发送到父构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建类继承,其中我的新类创建父类的对象,设置一些默认参数(它们是指向其他对象的指针)。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆