我有以下具有虚拟GrandParent
和非虚拟Parent
和Child
的类层次结构:
class GrandParent {
protected:
explicit GrandParent(const float &max_dur);
virtual ~GrandParent() {}
private:
const float _max_dur;
};
class Parent : public virtual GrandParent {
public:
explicit Parent(const float &max_dur = 0);
};
class Child : public Parent {
public:
explicit Child(const float &max_dur = 0);
};
它们的构造函数嵌套如下:
// GrandParent constructor
GrandParent::GrandParent(const float &max_dur)
: _max_dur{max_dur} {}
// Use GrandParent constructor
Parent::Parent(const float &max_dur)
: GrandParent{max_dur} {}
// Use Parent constructor
Child::Child(const float &max_dur)
: Parent{max_dur} {} // <- error occurs here
当我构建时,我得到以下错误消息:
error: no matching function for call to ‘GrandParent::GrandParent()’
Codesnippet这里。
似乎忽略了Child
构造函数,而是跳转到GrandParent
。修改Child
构造函数以直接调用GrandParent
构造函数(从而跳过一代),我可以绕过错误,但这似乎是错误的方法。
提前感谢您的帮助!
<标题>解决方案修复了463035818-is-not-a-number对显式调用GrandParent
的构造函数的回答和对同时调用Parent
的构造函数的建议:
Child::Child(const float &max_dur)
: GrandParent{max_dur}, Parent{max_dur} {}
标题>来自faq:
当我从使用虚拟继承的类继承时,我需要知道哪些特殊的注意事项?
派生类的初始化列表直接调用虚基类的ctor。
因为虚基类的子对象在实例中只出现一次,所以有特殊的规则来确保虚基类的构造函数和析构函数在每个实例中只被调用一次。c++规则规定在所有非虚基类之前构造虚基类。作为一名程序员,你需要知道的是:在你的类继承层次结构中的任何地方,虚拟基类的构造函数都是由"最派生"类的构造函数调用的。
Child
的构造函数直接调用GrandParent
的构造函数,因为GrandParent
是虚基。因为没有显式地调用它,所以调用了默认构造函数,但是GrandParent
没有默认构造函数。
修改子构造函数以直接调用祖父母构造函数(从而跳过一代),我可以绕过错误,但这似乎是错误的方法。
这正是正确的方法。Child
的构造函数确实调用GrandParent
的构造函数,当GrandParent
是虚基类而Child
是派生最多的类时,您无法对此做任何事情。你可以做的是:选择正确的构造函数,而不是让编译器尝试调用不存在的默认构造函数。