c++ - 菱形继承(钻石问题)两次派生 - 构造函数参数不同 - 找不到指定虚拟继承的基础

标签 c++ interface multiple-inheritance diamond-problem

我努力在标题中简洁地描述问题,所以如果您了解问题并有更好的标题,请推荐。

我已经制作了我的问题的精简版,它尽可能小,因此所有函数都是内联定义的,所以请原谅,实际代码不是这样的。

这是我的结构:

class iobject
{
public:
    virtual bool isValid (void) = 0;
};

class object : virtual public iobject
{
public:
    object (void) { }
    virtual ~object () {}
    virtual bool isValid (void) { return true; }
};

所以上面,一个接口(interface)+实现,它简单地跟踪一个对象是否有效......想象一下引擎/系统中的所有对象都将派生自这个单一对象。

class ibase : public virtual iobject
{
public:
    virtual void show (void) = 0;
};

class base : public virtual object,
             public virtual ibase
{
public:
    base (int value) : object() { m_value = value; }
    virtual ~base () {}
    virtual void show (void) { std::cout << m_value << std::endl; }

private:
    int m_value;
};

现在我有一个假设的类,它只是存储一个数字并打印它。它源自对象。这样“钻石”就完成了。

class derived1 : public virtual base
{
public: 
    derived1 (int value) : base (value) {}
    virtual ~derived1 () {}
};

现在我从基类派生。这个派生类需要注意的是我有和基类相同的构造函数参数(int值)。

class derived2 : public virtual derived1
{
public:
    derived2 (void) : derived1 (15) {}
    virtual ~derived2 () {}
};

最后我派生自这个派生类。但是,请注意此类没有任何构造函数参数。相反,这个类在内部应该知道这个例子中的值应该是 15。

我的期望是,当我实例化 derived2 时,它会构造值为 15 的 derived1 并将其传递给对象。我希望做到以下几点:

derived1 works(1234);
derived2 doesNotWork;

works.show();
doesNotWork.show();

但是当我尝试这样做时,我得到:

error C2512: 'base::base' : no appropriate default constructor available

如果我添加一个空的 base::base 构造函数,那么我最终会像我预期的那样 m_value 未定义(但无论如何都尝试过)

我似乎遗漏了一些明显的东西...,有人可以突出显示吗?

最佳答案

将 derived2 更改为:

derived2(void) : derived1(15), base(15) {}

这里出现了同样的问题: Why is Default constructor called in virtual inheritance?

这个常见问题解答中描述了答案: http://www.parashift.com/c++-faq-lite/virtual-inheritance-ctors.html

简而言之:C++ 不分层调用虚构造函数。最派生类负责调用所有虚基类的构造函数。因此,您必须显式调用 derived1() 和 base(),因为它们采用参数。链接的常见问题解答暗示此处的最佳实践是使虚拟基类仅具有无参数构造函数。

关于c++ - 菱形继承(钻石问题)两次派生 - 构造函数参数不同 - 找不到指定虚拟继承的基础,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24543584/

相关文章:

c++ - 派生类中基构造函数的控制,潜在的双重初始化

C++ COM接口(interface)继承

c# - 在父/接口(interface)中使用子类型

java - 在 Java 中实现曾经是 Mixin 的正确方法?

c++ - ‘{’ 标记 { 之前的预期类名

c++ - 阶梯式 C++ 虚拟继承

c++ - 如何使继承的基类使用公共(public)变量

Python:为什么 MRO 中的最后一个类在其 super 的 __init__ 调用中应该有零参数,否则会出现运行时异常

c++ - C++中的方法链接?

java - 如何在我的界面中为最终变量创建 Java 字段注释