• C++ 对象内存布局


    单一的一般继承

     

    可见以下几个方面:

    1. 虚函数表在最前面的位置

    2. 成员变量根据其继承和声明的顺序一次放在后面

    3. 在单一继承中, 被 overwrite 的虚函数在虚函数表中得到更新

    多重继承

    我们可以看到

    1. 每个父类都有自己的虚函数表

    2. 子类的成员函数被放在第一个父类的表中

    3. 内存布局中, 父类按照声明顺序一次排列

    4. 每个父类的虚表中的 f() 函数都被 overwrite 成了子类的 f(). 这样做就是为了解决不同父类类型的指针指向同一个子类实例.

    重复继承

    我们可以看到, 最顶端的父类 B 其成员变量存在于 B1 和 B2 中, 并被 B 给继承下来了. 而在 D 中, 其有 B1 和 B2 的实例, 于是 B 的成员在 D 的实例中存在两份, 一份是 B1 继承来的, 另一个份是 B1 继承来的. 所以, 我们使用如下语句, 则会产生二义性编译错误

    D d;

    d.ib = 0; // 二义性错误

    d.B1::ib = 1; // ok

    d.B2::ib = 2; // ok

    钻石型虚拟多重继承

     

    结论

    1. 一个 virtual base class 只会在 Derived class 中存在一份实体, 无论该基类被继承多少次

    2. (1) 的具体实现是将 D 对象分割成两部分, 分别是不变局部和共享局部. 不变局部部分, 无论后继如何演化, 总有固定的偏移量, 所以这部分数据可以直接存取. 至于共享局部, 表现出来的就是虚拟继承的基类子对象, 这一部分数据的位置随着派生操作而变化, 因此是间接存取.

    3. 一般的策略是存放不变局部, 然后在每一个派生对象中插入指针 vbptr, 每一个指针指向基类子对象

    4. 上图中, 第一个 vbptr 的值是 -4 和 40, 第二个是  -4 和 24. 40, 24 分别是 B1, B2 到基类子对象的偏移. -4 是 vbptr 到 _vfptr 的偏移.

    转自: http://www.cnblogs.com/liu-jun/archive/2013/05/17/3083736.html

    http://blog.csdn.net/haoel/article/details/3081328

  • 相关阅读:
    pip install selenium==版本号 报错
    解决phantomjs输出中文乱码
    phantomjs学习之网页访问测速
    phantomjs学习之截图
    bzoj1069-最大土地面积
    hdu4372-Count the Buildings
    bzoj3786-星系探索
    Codeforces633H-Fibonacci-ish II
    hdu3625-Rooms
    斯特林数
  • 原文地址:https://www.cnblogs.com/zhouzhuo/p/3640749.html
Copyright © 2020-2023  润新知