C ++虚拟继承奇怪的行为[重复]

问题描述 投票:-3回答:2

这个问题在这里已有答案:

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中编译。您可以将这一继承线想象为双钻石问题。

c++ inheritance virtual
2个回答
3
投票

这毫无意义。

为什么?这正是虚拟继承的用途。在A中只有一个G子对象。当我们沿着等级划分时,说明者坚持,所以即使G有两个D,他们都共享一个A


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碱基都是虚拟的。

© www.soinside.com 2019 - 2024. All rights reserved.