直接继承和虚继承的内存布局

来源:互联网 发布:mac怎么设置手机铃声 编辑:程序博客网 时间:2024/06/05 04:38

直接继承

(原文链接:点击打开链接)

(1)无虚函数覆盖的单继承:

子类对象的内存布局:虚表指针、父类成员变量、子类成员变量

虚函数表的布局:父类的虚函数地址(按声明顺序)、子类自定义的虚函数的地址(按声明顺序)

(2)有虚函数覆盖的单继承

子类对象的内存布局:虚表指针、父类成员变量、子类成员变量
虚函数表的布局:子类已覆盖的虚函数的地址、父类中未被覆盖的虚函数的地址、子类自定义的虚函数的地址

(3)无虚函数覆盖的多继承

子类对象的内存布局:父类1的虚表指针、父类1的成员变量、父类2的虚表指针、父类2的成员变量
父类1虚函数表的布局:父类1的虚函数地址、子类自定义的虚函数的地址

父类2虚函数表的布局:父类2的虚函数地址

(4)有虚函数覆盖的多继承

子类对象的内存布局:父类1的虚表指针、父类1的成员变量、父类2的虚表指针、父类2的成员变量
父类1虚函数表的布局:子类已覆盖的虚函数的地址、父类中未被覆盖的虚函数的地址、子类自定义的虚函数的地址
父类2虚函数表的布局:子类已覆盖的虚函数的地址、父类中未被覆盖的虚函数的地址

总结:

直接继承的多继承中,继承了几个父类,就要维护几个虚函数表,并且为他们分配指针。

直接继承的多继承中,子类的自定义虚函数总是放在第一个父类的虚函数表的末尾。

直接继承的多继承中,如果发生菱形继承,那么子类对象的内存布局中不会做优化,比如说A派生B、C,D再多继承B、C,那么D类的对象会保存两个A类成员变量的副本。
但是虚继承的多继承中,如果发生菱形继承,那么
B对象的内存布局为:父类A的虚表指针、B自己的成员变量、父类A的成员变量
C对象的内存布局为:父类A的虚表指针、C自己的成员变量、父类A的成员变量
D对象的内存布局为:父类B的虚表指针、父类B的成员变量、父类C的虚表指针、父类C的成员变量、D自己的成员变量、祖父类A的成员变量。
即只维护一个祖父类成员变量的副本,节省了空间。(引用链接:点击打开链接)































原创粉丝点击