C ++的多重继承是如何实现的?

时间:2009-06-16 16:11:37

标签: c++ inheritance compiler-construction multiple-inheritance language-implementation

单继承易于实现。例如,在C中,继承可以模拟为:

struct Base { int a; }
struct Descendant { Base parent; int b; }

但是对于多重继承,编译器必须在新构造的类中安排多个父项。怎么做?

我看到的问题是:父母应该安排在AB或BA中,还是以其他方式安排?然后,如果我做演员:

SecondBase * base = (SecondBase *) &object_with_base1_and_base2_parents;

编译器必须考虑是否更改原始指针。虚拟化需要类似的棘手事项。

7 个答案:

答案 0 :(得分:10)

C ++创建者的以下文章描述了多重继承的可能实现:

Multiple Inheritance for C++ - Bjarne Stroustrup

答案 1 :(得分:5)

关于如何在VC ++中实现它有this pretty old MSDN article

答案 2 :(得分:5)

  

然后,如果我做演员:

SecondBase base = (SecondBase *) object_with_base1_and_base2_parents;
     

编译器必须考虑是否更改原始指针。虚拟的类似棘手的东西。

使用非虚拟继承,这不像你想象的那么棘手 - 在编译强制转换时,编译器知道派生类的确切布局(毕竟,编译器完成了布局)。通常所有发生的事情都是从派生类指针中添加/减去固定偏移量(对于其中一个基类可能为零)。

对于虚拟继承,它可能有点复杂 - 它可能涉及从vtbl(或类似)获取偏移量。

Stan Lippman的书"Inside the C++ Object Model"非常好地描述了这些东西可能(通常确实如此)的作用。

答案 3 :(得分:1)

父母按照他们指定的顺序排列:

class Derived : A, B {} // A comes first, then B

class Derived : B, A {} // B comes first, then A

您的第二种情况是以特定于编译器的方式处理的。一种常见的方法是使用大于平台指针大小的指针来存储额外的数据。

答案 4 :(得分:1)

这是一个有趣的问题,实际上不是C ++特有的。当你的语言具有多个调度以及多重继承(例如CLOS)时,事情也变得更加复杂。

人们已经注意到有不同的方法可以解决这个问题。您可能会在此上下文中阅读有关元对象协议(MOP)的一些内容......

答案 5 :(得分:0)

完全取决于编译器是如何完成的,但我相信它通常是通过vtable的层次结构完成的。

答案 6 :(得分:0)

我进行了简单的实验:

class BaseA { int a; };
class BaseB { int b; };
class Descendant : public BaseA, BaseB {};
int main() {
        Descendant d;
        BaseB * b = (BaseB*) &d;
        Descendant *d2 = (Descendant *) b;
        printf("Descendant: %p, casted BaseB: %p, casted back Descendant: %p\n", &d, b, d2);
}

输出是:

Descendant: 0xbfc0e3e0, casted BaseB: 0xbfc0e3e4, casted back Descendant: 0xbfc0e3e0

很高兴认识到静态铸造并不总是意味着“在不触及内容的情况下改变类型”。 (好吧,当数据类型不相互适应时,内容也会受到干扰,但IMO的情况也不同。)