子构造函数使用祖父构造函数

Child constructor uses grandparent constructor

我有以下 class 层次结构,具有虚拟 GrandParent 和非虚拟 ParentChild:

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 here.

似乎忽略了 Child 构造函数,而是跳转到 GrandParent。修改 Child 构造函数直接调用 GrandParent 构造函数(从而跳过了一代),我可以绕过错误,但似乎是错误的做法。

在此先感谢您的帮助!

解决方案

通过遵循 显式调用 GrandParent 的构造函数和康桐蔚的建议以调用 Parent 的构造函数进行修复:

Child::Child(const float &max_dur)
    : GrandParent{max_dur}, Parent{max_dur} {}

来自faq

What special considerations do I need to know about when I inherit from a class that uses virtual inheritance?

Initialization list of most-derived-class’s ctor directly invokes the virtual base class’s ctor.

Because a virtual base class subobject occurs only once in an instance, there are special rules to make sure the virtual base class’s constructor and destructor get called exactly once per instance. The C++ rules say that virtual base classes are constructed before all non-virtual base classes. The thing you as a programmer need to know is this: constructors for virtual base classes anywhere in your class’s inheritance hierarchy are called by the “most derived” class’s constructor.

Child的构造函数直接调用了GrandParent的构造函数,因为GrandParent是虚基。并且因为你没有显式调用它,所以调用了默认构造函数,但是GrandParent没有默认构造函数。

Modifying the Child constructor to directly call the GrandParent constructor (thus skipping a generation), I can bypass the error but it seems like the wrong approach.

这是完全正确的方法。 Child 的构造函数确实调用了 GrandParent 的构造函数,当 GrandParent 是虚拟基而 Child 是最派生的 class 时,您对此无能为力.你可以做的是:选择正确的构造函数,而不是让编译器尝试调用不存在的默认构造函数。