【发布时间】:2021-07-17 01:01:04
【问题描述】:
我在一个层次结构中有 3 个类(称为 A、B 和 C),其中 B 扩展 A,C 扩展 B。A 类有一个接受单个参数的构造函数。 C 的定义要求调用 A 的构造函数,因此我试图通过在 B 中创建构造函数来实现这一点。但是,编译器告诉我 C 的构造函数必须同时初始化 A 和 B。这对我来说似乎违反直觉,因为它真的应该只初始化一次。
以下代码可以更好地说明我面临的问题:
#include <iostream>
struct A {
A(std::string name) : name_(name) {
std::cout << "A ctor called: " << name << std::endl;
}
std::string name_;
};
struct B : virtual public A {
// This constructor is required or else subclasses cannot be constructed properly
B(std::string name) : A(name) {
std::cout << "B ctor called: " << name << std::endl;
}
};
struct C : virtual public B {
// ERROR: constructor for 'C' must explicitly initialize the base class 'A' which does not have a default constructor
// C() : B("hey") {}
// ERROR: constructor for 'C' must explicitly initialize the base class 'B' which does not have a default constructor
// C() : A("hey") {}
// ok... but have to pass the same name twice & init'ed twice!
C() : A("wat"), B("hey") {
std::cout << "C ctor called" << std::endl;
}
// gcc reorders the constructor invocations...
// here it's written as B then A but it would be init'ed in the order of A then B
// C() : B("hey"), A("wat") {
// std::cout << "C ctor called" << std::endl;
// }
// ok... we can just pass a name but it's still init'ed twice!
// C(std::string name) : B(name), A(name) {}
};
int main() {
C c;
std::cout << c.name_ << std::endl;
}
当我运行代码时,我得到了:
A ctor called: wat
B ctor called: hey
C ctor called
wat
我的问题是:
-
有没有更简洁的方法来编写它,这样我就不必显式调用 A 和 B 的构造函数?
-
为什么输出显示
hey是稍后设置的,但name_字段包含wat(之前设置)?
【问题讨论】:
-
虚拟基类由最派生的对象构造(因此,在您的层次结构中,C 将首先构造 A,然后构造 B)。你有必要使用虚拟基类吗?
-
virtual继承意味着派生最多的类必须调用构造函数。如果它们有默认构造函数,那么您不必显式调用它们。 B的构造函数在构造C时不会调用A的构造函数。 -
OK,制作
struct B : public A解决了这个问题。在这种情况下,我实际上并不需要它是虚拟的。谢谢。