我努力在标题中简洁地描述问题,所以如果你理解了这个问题并且有更好的标题,请建议。
我已经制作了我的问题的精简版本,它尽可能小,因此所有函数都是内联定义的,所以请原谅,实际代码不是这样的。
这是我的结构:
class iobject
{
public:
virtual bool isValid (void) = 0;
};
class object : virtual public iobject
{
public:
object (void) { }
virtual ~object () {}
virtual bool isValid (void) { return true; }
};
如上所述,一个接口+实现只是跟踪一个对象是否有效......想象一下,引擎/系统中的所有对象都将来自这个单个对象。
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;
};
现在我有一个假设的课程,除了存储一个数字并打印它之外什么也没做。它源于对象。所以&#39;钻石&#39;已经完成了。
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未定义的预期(但无论如何都要尝试)
我似乎错过了一些明显的东西......,有人能突出它吗?
答案 0 :(得分:1)
将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(),因为它们接受参数。链接的FAQ意味着这里的最佳实践是使虚拟基类只有no-arg构造函数。
答案 1 :(得分:0)
你没有钻石继承,这里没有共享基类(derived2 - &gt; derived1 - &gt; base - &gt;(object - &gt; iobject),ibase),无处可去链是否有任何重复。因此,您不需要虚拟继承,因此只需将public virtual
全部删除即可。我意识到这是一个人为的例子而且与你的实际用法并不匹配,但根据我的经验,你真的需要多次继承虚拟调用,这是你通常应该远离的事情。在所有可能的情况下(对象大小,调用开销以及指针表现的一般肮脏)。