zoukankan      html  css  js  c++  java
  • C++学习之路: 虚继承的内存的模型

    写给出结论:

    1.类大小计算遵循结构体对其原则

    2.类的大小与数据成员有关,与成员函数无关

    3.类的大小与静态数据成员无关

    4. 虚继承对类的大小影响

    5.虚函数对类的大小影响

    研究背景)

    我们以这个钻石型继承来研究下,虚继承后派生类DD的内存分布,先说原理和推测,来理解编译器的处理是如何在内存上体现的。

    保持我们一贯的做风。

    image

    #include <iostream>
    using namespace std;
    
    
    class BB
    {
    public:
        int bb_;
    };
    
    class B1 : virtual public BB
    {
    public:
        int b1_;
    };
    
    class B2 : virtual public BB
    {
    public:
        int b2_;
    };
    
    class DD : public B1, public B2
    {
    public:
        int dd_;
    };
    
    int main(void)
    {
        cout<<sizeof(BB)<<endl;
        cout<<sizeof(B1)<<endl;
        cout<<sizeof(DD)<<endl;
    
        B1 b1;
        long** p;
        
        cout<<&b1<<endl;
        cout<<&b1.bb_<<endl;
        cout<<&b1.b1_<<endl;
    
        p = (long**)&b1;
        cout<<p[0][0]<<endl;
        cout<<p[0][1]<<endl;
    
        DD dd;
        cout<<&dd<<endl;
        cout<<&dd.bb_<<endl;
        cout<<&dd.b1_<<endl;
        cout<<&dd.b2_<<endl;
        cout<<&dd.dd_<<endl;
        p = (long**)&dd;
        cout<<p[0][0]<<endl;
        cout<<p[0][1]<<endl;
        cout<<endl;
        cout<<p[2][0]<<endl;
        cout<<p[2][1]<<endl;
    
        BB* pp;
    
        pp = &dd;
        pp->bb_;        // ͨ¹ý¼ä½Ó·ÃÎÊ£¬ÕâÐèÒªÔËÐÐʱµÄÖ§³Ö
    
        return 0;
    }

    结果打印

    4
    12
    24
    0xbfacd81c
    0xbfacd824
    0xbfacd820
    0
    134515772
    0xbfacd804
    0xbfacd818
    0xbfacd808
    0xbfacd810
    0xbfacd814
    12
    -8
    
    134515700
    134515740

    根据结果,我们可以把几个类的内存分布画出来

    @B1的内存分布,可以通过照相记忆法。

    有以下特点

    image

    1。 一般来说编译器都会把虚继承的基类放置在内存底部,和构造顺序是一致的,在小端机上是

    高地址存放低字节,所以先构造bb_基类放置在底部。然后构造自身是B1

    空白处世虚基类表指针,也占据4个字节

    image

    vbptr虚基类指针指向一个虚基类表,这个表记录着两个偏移量,

    已在图上标注,*(指针和本地址的差) *(指针和虚基类的差),大家自己减一下就可以算出偏移量分布式0和8;

    @DD对象:多虚基类继承下的内存分布

    image

    可以看的出内存分布和和继承,与构造顺序的关系,基类总是先被构造,继承离最远派生类越远,越先构造,所以看到,基类BB最先被构造,然后是B2,最后是B1。

    当B1构造结束,那么整个DD类便构造完成了

    结论:通过派生类指针访问虚基类数据成员,需要在运行时动态的找到偏移地址,

    数据间接访问。

  • 相关阅读:
    UVa 11384 Help is needed for Dexter (递归)
    HDU 4355 Party All the Time (三分求极值)
    UVa 11992 Fast Matrix Operations (线段树,区间修改)
    LA 3708 && POJ 3154 Graveyard (思维)
    LA 3942 && UVa 1401 Remember the Word (Trie + DP)
    LA 4329 Ping pong (树状数组)
    HDU 2058 The sum problem (数学+暴力)
    POJ 1458 Common Subsequence (DP+LCS,最长公共子序列)
    代理服务器
    .net垃圾回收
  • 原文地址:https://www.cnblogs.com/DLzhang/p/4732293.html
Copyright © 2011-2022 走看看