C ++纯虚拟多重继承?

时间:2014-09-12 10:40:02

标签: c++ inheritance virtual multiple-inheritance

对于使用Interfaces的多重继承的实现,我需要帮助...

现有的代码有一个具有很多功能的接口。实例是使用工厂创建的。

class IBig
{
    // Lot of pure virtual functions
};

他的补充:

class CBig: public IBig
{
    // Implementation
}

我想在多个较小的接口中拆分接口,但它应该与现有代码保持一段时间兼容。

以下是我尝试做的一个示例:

class IBaseA
{
public:
    virtual void DoA() = 0;
};

class IBaseB
{
public:
    virtual void DoB() = 0;
};

// The same interface, now based on multiple smaller interfaces
class IBig : public IBaseA, public IBaseB
{
};

class CBaseA: public IBaseA
{
public:
    virtual void DoA()
    {
        printf("DoA\n");
    }
};

class CBaseB: public IBaseB
{
public:
    virtual void DoB()
    {
        printf("DoB\n");
    }
};

// Inherit from base classes where the implementation is, and from IBig as 
// the instance of CBig is returned as IBig.
class CBig: public CBaseA, public CBaseB, public IBig
{
};

这里的问题是CBig类无法实现。编译器说DoA和DoB函数是纯虚函数,即使它们是在CBaseA和CBaseB中实现的。如果我不想再次实现这些函数,只需要调用基类的函数,我该怎么办?

注意:我知道设计很难看,但这只是暂时的,直到可以更换大界面,而且......我想明白! ; - )

提前致谢!

2 个答案:

答案 0 :(得分:14)

在这里,您应该使用虚拟继承。此功能可确保在实例化子类时,只有一个虚拟继承的基类实例。对于您的示例,这看起来像:

#include <cstdio>

class IBaseA
{
public:
    virtual void DoA() = 0;
};

class IBaseB
{
public:
    virtual void DoB() = 0;
};

// The same interface, now based on multiple smaller interfaces
class IBig : virtual public IBaseA,  virtual public IBaseB
//              ^                       ^
{
};

class CBaseA: virtual public IBaseA
//              ^
{
public:
    virtual void DoA()
    {
        printf("DoA\n");
    }
};

class CBaseB: virtual public IBaseB
//              ^
{
public:
    virtual void DoB()
    {
        printf("DoB\n");
    }
};

// Inherit from base classes where the implementation is, and from IBig as 
// the instance of CBig is returned as IBig.
class CBig: public CBaseA, public CBaseB, public IBig
{
};

int main()
{
    CBig cb;
}

以上更改可确保在您多次从DoADoB继承时,未创建IBaseAIBaseB的额外声明。

答案 1 :(得分:3)

这被称为死亡的致命钻石(或简称钻石问题)。之所以发生这种情况,是因为CBig继承自共享公共基类的类。

您可以通过为其所属的类前缀

来调用正确的DoA
CBaseA::doA();

或者您使用虚拟继承只有一个IBaseA和IBaseB实例

class CBaseA : public virtual IBaseA {};
class CBaseB : public virtual IBaseB {};
class IBig : public virtual IBaseA, public virtual IBaseB {};

依旧......