gpt4 book ai didi

c++ - 虚继承和基类的基类

转载 作者:太空狗 更新时间:2023-10-29 21:42:03 27 4
gpt4 key购买 nike

考虑以下代码:

class A {
};

class B : public A {
};

class C : public B{
public:
C() : A() {} // ERROR, A is not a direct base of B
};

在这种情况下,GCC(4.8.1,C++99)给出了正确的错误(我理解这种行为):

prog.cpp:12:8: 错误:类型“a”不是“c”的直接基础

但是,如果 b 和 a 之间的继承是虚拟的,则不会发生这种情况:

class A {
};

class B : virtual public A {
};

class C : public B{
public:
C() : A() {} // OK with virtual inheritance
};

为什么会这样?A 现在是否被编译器视为 C 的直接基类?

最佳答案

一般来说,因为这就是 C++ 试图解决菱形继承问题的方式 http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem (无论是好的还是坏的解决方案都留给读者作为练习)。

所有继承都是 is-a 和 has-a 关系的组合……您必须实例化父实例。如果您有以下类(class):

class a;
class b : a;
class c : a;
class d : b,c;

然后您为每个 b 和 c 实例化了一个 a。 d 将不知道使用哪个 a。

C++ 通过允许虚拟继承解决了这个问题,这是一种高开销的继承,允许 b 和 c 在 d 中继承时共享相同的 a(它比那复杂得多,但你可以自己阅读).

链中最派生的类型需要能够覆盖共享类的实例化,以控制共享类在父类中继承方式的差异。举个例子:

class a {int x; public: a(int xx) {x=xx;} int get_x() {return x;}};
class b : public virtual a { public: b(): a(10){}};
class c : public virtual a { public: c(): a(15){}};
class d : public virtual b, public virtual c {public: d() : a (20) {}};
int main() {
d dd;
std::cout << dd.get_x() << std::endl;//20, d's constructor "wins"
return 0;
}

如果 d 没有定义 a 被实例化的内容,它将具有冲突实例化的定义(来自 bc)。 C++ 通过强制继承链中最派生的类来实例化所有父类来处理这个问题(如果 d 没有显式实例化 a,上面的代码将会失败,但是如果 a 提供了一个可以隐式使用的默认构造函数)并忽略所有父实例化。

关于c++ - 虚继承和基类的基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27317232/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com