C ++虚拟继承怪异行为

时间:2019-02-18 13:16:49

标签: c++ inheritance virtual

@AfterAll
@DisabledIfSystemProperty(named = "runTearDownScript", matches = "false")
void clearDownTestEnvironment() {
    System.out.println(System.getProperty("runTearDownScript"));
}

输出代码为:

  • A
  • D
  • D
  • foo从A调用

这没有任何意义。对象D被构造两次。为何编译器不抱怨foo不明确? G如何知道foo上只有一个定义? (在这种情况下,D被创建了两次,我没有使用虚拟继承,但是以某种方式知道这一点。) 老实说,为了避免对foo的模棱两可,E和F实际上也应该是D固有的。 谁能提供一个很好的解释? 在VS 2017 Windows中编译。 您可以将这一继承行想象为 双重钻石问题。

2 个答案:

答案 0 :(得分:4)

  

对象D被构造了两次。

这是因为对象具有两个D基。一个通过E,另一个通过F

  

为什么编译器不会抱怨foo是模棱两可的?

因为只有一个A基。这是因为它是虚拟基础。每个具体实例始终只有一个其类型的虚拟基础子对象。

这是继承的粗略ASCII艺术:

non-virtual  |   virtual
             |   A
 ____________|__/
/   /  /  /  |
B  C  B  C   |
 \/    \/    |
  D     D    |
   \   /     |
    E  F     |       bases
_____\/______________________
      G              concrete
  

编译器如何知道多个D应该包含相同的基数A

因为它知道所有这些A碱基都是虚拟的。

答案 1 :(得分:3)

  

这没有道理。

为什么?这正是虚拟继承的目的。 A中只有一个G子对象。当我们沿着层次结构向下移动时,说明符会停留,因此即使G有两个D,它们也共享一个A