子类构造函数调用父类的父类构造函数。

3
我有以下类层次结构,其中包含虚拟的 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()’

这里有代码片段

看起来好像Child构造函数被忽略了,而直接跳到了GrandParent。将Child构造函数修改为直接调用GrandParent的构造函数(从而跳过一代),可以避免错误,但这似乎是错误的方法。

感谢您的帮助!

解决方案

按照463035818-is-not-a-number的答案的建议显式地调用GrandParent的构造函数,并按照康桓瑋的建议调用Parent的构造函数即可解决问题:

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

4
需要添加 GrandParent{max_dur},类似于 : Parent{max_dur}, GrandParent{max_dur} {} 的写法。 - 康桓瑋
你尝试过用圆括号替换花括号吗?:Parent(max_dur) - Refugnic Eternium
1个回答

4

来自常见问题解答

继承了使用虚拟继承的类,需要注意哪些特殊情况?

派生类构造函数的初始化列表直接调用虚拟基类的构造函数。

因为实例中仅包含一次虚拟基类子对象,所以有特殊规定保证每个实例只调用一次虚拟基类的构造函数和析构函数。C++规则规定,虚拟基类在所有非虚拟基类之前构造。作为程序员,你需要知道的是:你类继承层次结构中任何一个虚拟基类的构造函数都由“最派生”的类的构造函数调用。

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

修改Child的构造函数直接调用GrandParent的构造函数(跳过一代),我可以避免错误,但这似乎是错误的方法。

这正是正确的方法。当GrandParent是虚基类而Child是最派生类时,Child的构造函数确实调用了GrandParent的构造函数,你无法对此进行任何更改。你能做的是:选择正确的构造函数,而不是让编译器尝试调用不存在的默认构造函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接