C++ 虚拟继承奇怪的行为
C++ Virtual Inheritance weird behavior
struct A {
public:
A() {
std::cout << "A" << std:: endl;
}
void foo() { std::cout << "foo is called from A"; }
};
struct B : virtual A { };
struct C : virtual A { };
struct D : B, C { D() { std::cout << "D" << std::endl; } };
struct E : D { };
struct F : D {};
struct G : E, F {};
int main()
{
G g;
g.foo();
}
输出代码为:
- 一个
- D
- D
- foo 是从 A
调用的
这毫无意义。对象 D 被构造了两次。为什么编译器不抱怨 foo 不明确?
G 如何知道 foo 上只有一个定义? (在这种情况下,D 被制作了两次,我没有使用虚拟继承,但不知何故它知道。)
老实说,我认为 E 和 F 实际上也应该从 D 继承,以避免 foo 的模糊定义。
任何人都可以提供一个很好的解释吗?
在 VS 2017 中编译 Windows。
你可以把这条继承线想象成一个双菱形问题
Object D is constructed twice.
这是因为该对象有两个 D
碱基。一个通过 E
,另一个通过 F
。
Why doesn't the compiler complain that foo is ambiguous?
因为只有一个A
基地。这是因为它是一个虚拟基地。对于每个具体实例,总是只有一个其类型的虚拟基础子对象。
这是继承的粗略 ASCII 艺术:
non-virtual | virtual
| A
____________|__/
/ / / / |
B C B C |
\/ \/ |
D D |
\ / |
E F | bases
_____\/______________________
G concrete
How does the compiler know that multiple D should contain the same base A
因为它知道所有这些 A 碱基都是虚拟的。
This makes no sense.
为什么?这正是虚拟继承的目的。 G
中只有一个 A
子对象。说明符在我们沿着层次结构向下移动时保持不变,因此即使 G
有两个 D
,它们都共享一个 A
.
struct A {
public:
A() {
std::cout << "A" << std:: endl;
}
void foo() { std::cout << "foo is called from A"; }
};
struct B : virtual A { };
struct C : virtual A { };
struct D : B, C { D() { std::cout << "D" << std::endl; } };
struct E : D { };
struct F : D {};
struct G : E, F {};
int main()
{
G g;
g.foo();
}
输出代码为:
- 一个
- D
- D
- foo 是从 A 调用的
这毫无意义。对象 D 被构造了两次。为什么编译器不抱怨 foo 不明确? G 如何知道 foo 上只有一个定义? (在这种情况下,D 被制作了两次,我没有使用虚拟继承,但不知何故它知道。) 老实说,我认为 E 和 F 实际上也应该从 D 继承,以避免 foo 的模糊定义。 任何人都可以提供一个很好的解释吗? 在 VS 2017 中编译 Windows。 你可以把这条继承线想象成一个双菱形问题
Object D is constructed twice.
这是因为该对象有两个 D
碱基。一个通过 E
,另一个通过 F
。
Why doesn't the compiler complain that foo is ambiguous?
因为只有一个A
基地。这是因为它是一个虚拟基地。对于每个具体实例,总是只有一个其类型的虚拟基础子对象。
这是继承的粗略 ASCII 艺术:
non-virtual | virtual
| A
____________|__/
/ / / / |
B C B C |
\/ \/ |
D D |
\ / |
E F | bases
_____\/______________________
G concrete
How does the compiler know that multiple D should contain the same base A
因为它知道所有这些 A 碱基都是虚拟的。
This makes no sense.
为什么?这正是虚拟继承的目的。 G
中只有一个 A
子对象。说明符在我们沿着层次结构向下移动时保持不变,因此即使 G
有两个 D
,它们都共享一个 A
.