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

use*_*414 4 c++ inheritance

我有以下带有虚拟GrandParent和非虚拟的Parent类层次结构Child

\n
class GrandParent {\nprotected:\n    explicit GrandParent(const float &max_dur);\n    virtual ~GrandParent() {}\n\nprivate:\n    const float _max_dur;\n};\n\nclass Parent : public virtual GrandParent {\npublic:\n    explicit Parent(const float &max_dur = 0);\n};\n\nclass Child : public Parent {\npublic:\n    explicit Child(const float &max_dur = 0);\n};\n
Run Code Online (Sandbox Code Playgroud)\n

它们的构造函数是这样嵌套的:

\n
// GrandParent constructor\nGrandParent::GrandParent(const float &max_dur)\n    : _max_dur{max_dur} {}\n\n// Use GrandParent constructor\nParent::Parent(const float &max_dur)\n    : GrandParent{max_dur} {}\n\n// Use Parent constructor\nChild::Child(const float &max_dur)\n    : Parent{max_dur} {}                        // <- error occurs here\n
Run Code Online (Sandbox Code Playgroud)\n

当我构建时,我收到以下错误消息:

\n
error: no matching function for call to \xe2\x80\x98GrandParent::GrandParent()\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n

代码片段在这里

\n

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

\n

在此先感谢您的帮助!

\n

解决方案

\n

通过遵循463035818-is-not-a-number\'s 答案显式调用GrandParent\'s 构造函数和 \xe5\xba\xb7\xe6\xa1\x93\xe7\x91\x8b\'s 建议来修复Parent也调用\ 的构造函数:

\n
error: no matching function for call to \xe2\x80\x98GrandParent::GrandParent()\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n

for*_*818 5

来自常见问题解答

\n
\n

当我从使用虚拟继承的类继承时,我需要了解哪些特殊注意事项?

\n

最派生类\xe2\x80\x99s ctor的初始化列表直接调用虚拟基类\xe2\x80\x99s ctor。

\n

由于虚拟基类子对象在实例中仅出现一次,因此有特殊规则来确保每个实例准确调用虚拟基类\xe2\x80\x99s 构造函数和析构函数一次。C++ 规则规定,虚拟基类是在所有非虚拟基类之前构造的。作为程序员,您需要知道的是:您的类\xe2\x80\x99s继承层次结构中任何位置的虚拟基类的构造函数都由\xe2\x80\x9c最派生的\xe2\x80\x9d类\xe2\调用x80\x99s 构造函数。

\n
\n

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

\n
\n

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

\n
\n

这正是正确的做法。Childs 构造函数确实调用了GrandParents 构造函数,当GrandParent是虚拟基并且Child是最派生类你能做的是:选择正确的构造函数,而不是让编译器尝试调用不存在的默认构造函数。

\n