22

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

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

但是对于多重继承,编译器必须在新构造的类中安排多个父级。它是如何完成的?

我看到的问题是:父母应该安排在AB还是BA,或者甚至其他方式?然后,如果我进行演员表:

SecondBase * base = (SecondBase *) &object_with_base1_and_base2_parents;

编译器必须考虑是否改变原始指针。虚拟机也需要类似的棘手事情。

4

7 回答 7

13

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

C++ 的多重继承- Bjarne Stroustrup

于 2009-06-16T16:15:39.763 回答
5

一篇相当古老的 MSDN 文章介绍了它是如何在 VC++ 中实现的。

于 2009-06-16T16:13:55.083 回答
5

然后,如果我进行演员表:

SecondBase base = (SecondBase *) object_with_base1_and_base2_parents;

编译器必须考虑是否改变原始指针。与虚拟机类似的棘手事情。

使用非虚拟继承,这比你想象的要简单——在编译转换时,编译器知道派生类的确切布局(毕竟,编译器做了布局)。通常所发生的只是从派生类指针中添加/减去固定偏移量(对于基类之一可能为零)。

对于虚拟继承,它可能会更复杂一些——它可能涉及从 vtbl(或类似的)获取偏移量。

Stan Lippman 的书“深入 C++ 对象模型”很好地描述了这些东西可能(并且通常确实如此)如何工作。

于 2009-06-16T16:44:10.657 回答
1

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

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

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

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

于 2009-06-16T16:16:20.403 回答
1

这是一个有趣的问题,实际上并不是 C++ 特定的。当您拥有一种具有多重分派和多重继承的语言(例如 CLOS)时,事情也会变得更加复杂。

人们已经注意到有不同的方法来解决这个问题。在这种情况下,您可能会发现阅读一些有关元对象协议 (MOP) 的有趣内容......

于 2009-06-16T16:24:57.673 回答
0

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

于 2009-06-16T16:14:20.203 回答
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 情况不同)。

于 2009-06-17T18:04:30.980 回答