子构造函数使用祖父构造函数
Child constructor uses grandparent constructor
我有以下 class 层次结构,具有虚拟 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()’
似乎忽略了 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 时,您对此无能为力.你可以做的是:选择正确的构造函数,而不是让编译器尝试调用不存在的默认构造函数。
我有以下 class 层次结构,具有虚拟 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()’
似乎忽略了 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 时,您对此无能为力.你可以做的是:选择正确的构造函数,而不是让编译器尝试调用不存在的默认构造函数。