【发布时间】:2019-01-25 09:06:12
【问题描述】:
在下面的代码中,我在最派生类Grandchild 中初始化Base 类的成员const。
class Base {
public:
Base(int x_) : x(x_) {}
private:
const int x;
};
class Child : public virtual Base {
public:
virtual ~Child() = 0;
};
class Grandchild : public virtual Child {
public:
Grandchild() : Base(42) {}
};
Child::~Child() {}
int main() {
Grandchild gc;
}
在虚拟继承的情况下,Base 类的构造函数由最派生的类调用。因此,我希望代码能够成功编译。
clang 4.0 编译成功,而 gcc 4.9.2 发出以下错误:
In constructor 'Grandchild::Grandchild()':
16:27: error: use of deleted function 'Child::Child()'
9:7: note: 'Child::Child()' is implicitly deleted because the default definition would be ill-formed:
9:7: error: no matching function for call to 'Base::Base()'
9:7: note: candidates are: 3:5: note: Base::Base(int)
3:5: note: candidate expects 1 argument, 0 provided
1:7: note: constexpr Base::Base(const Base&)
1:7: note: candidate expects 1 argument, 0 provided
1:7: note: constexpr Base::Base(Base&&)
1:7: note: candidate expects 1 argument, 0 provided
标准对此有何规定?
【问题讨论】:
-
@Ron 我不明白,使用虚拟继承有什么问题吗?无论如何,我这样做是因为我想在最派生的类中初始化基类成员。
-
只有在选择 C++11 时才会出现错误,使用 C++14 可以很好地实时编译:godbolt.org/z/nZdAln 也许您需要告诉您的编译器使用 C++14?跨度>
-
这就是虚拟继承类一直以来的工作方式。最派生类负责构建所有虚拟超类。
-
当然是 gcc 错误。 [class.base.init] 中有一条注释阐明了应该发生的情况:抽象类([class.abstract])永远不是最派生的类,因此它的构造函数永远不会初始化虚拟基类,因此对应的mem-initializers 可以省略。
Child就是这种情况。如果Child的虚析构函数被移除,那么所有编译器都会拒绝该代码并出现同样的错误。
标签: c++ constructor c++14 language-lawyer virtual-inheritance