zoukankan      html  css  js  c++  java
  • 【c++内存分布系列】单继承

      父类包括成员函数、静态函数、静态方法,子类包括成员函数、静态函数、静态方法的情况与一个类时完全一致,这里就不做分析了。子类单独包含虚函数时继承无关,也不做分析了。

      一、父类子类都为空

    #include <cstdio>
    
    class A
    {
    
    };
    
    class B: public A
    {
    
    };
    
    int main(int argc, char** argv)
    {
        printf("%d
    ", sizeof(B));
    }

      windows输出:

    1

      和一个空类时情况一致。

      二、父类包含成员变量、子类包含成员变量或子类父类都包含成员变量

    #include <cstdio>
    
    class A
    {
    public:
        int a;
    };
    
    class B: public A
    {
    
    };
    
    class AA
    {
    
    };
    
    class BB: public AA
    {
    public:
        int b;
    };
    
    class AAA
    {
    public:
        int a;
    };
    
    class BBB: public AAA
    {
    public:
        int b;
    };
    
    int main(int argc, char** argv)
    {
        printf("%d
    ", sizeof(B));
        printf("%d
    ", sizeof(BB));
        printf("%d
    ", sizeof(BBB));
    }

      windows输出:

    4
    4
    8

      内存为成员变量,包括父类的。

      三、父类包含虚函数,子类未实现该函数

    #include <cstdio>
    
    class A
    {
    public:
        int a;
        virtual void vfun(){};
    };
    
    class B: public A
    {
    
    };
    
    
    int main(int argc, char** argv)
    {
        printf("%d
    ", sizeof(B));
    
        B b;
        b.a = 0xaaaaaaaa;
        B* pb = &b;
        printf("%08x
    ", pb);
    }

      windows输出:

    8
    003ffe40

      查看对象b的内存:

    003FFE40 4C
    003FFE41 57
    003FFE42 22 00
    003FFE44 AA
    003FFE45 AA
    003FFE46 AA
    003FFE47 AA

      查看虚表0x0022574c:

    B::`vftable':
    0022574C 22 11 
    0022574E 22 00 
    00225750 00 00 
    00225752 00 00 

      查看虚表指向的地址:

    A::vfun:
    00221122 E9 19 04 00 00 jmp A::vfun (221540h)

    7: virtual void vfun(){};
    00221540 55 push ebp
    00221541 8B EC mov ebp,esp
    00221543 81 EC CC 00 00 00 sub esp,0CCh

      可知b.vfun()执行的是a的虚函数。

      四、父类包含虚函数、子类实现该函数

    #include <cstdio>
    
    class A
    {
    public:
        int a;
        virtual void vfun(){};
    };
    
    class B: public A
    {
    public:
        void vfun(){};
    };
    
    
    int main(int argc, char** argv)
    {
        printf("%d
    ", sizeof(B));
    
        B b;
        b.a = 0xaaaaaaaa;
        B* pb = &b;
        printf("%08x
    ", pb);
    }

      windows输出:

    8
    002bfc10

      查看对象b地址内容:

    002BFC10 4C
    002BFC11 57
    002BFC12 E7 00
    002BFC14 AA
    002BFC15 AA
    002BFC16 AA
    002BFC17 AA

      查看虚表0x00e7574c:

    B::`vftable':
    00E7574C 27  
    00E7574D 11 E7  
    00E7574F 00 00 

      查看该续表中的指针0x00e71127:

    B::vfun:
    00E71127 E9 24 04 00 00 jmp B::vfun (0E71550h)

    10: class B: public A
    11: {
    12: public:
    13: void vfun(){};
    00E71550 55 push ebp
    00E71551 8B EC mov ebp,esp
    00E71553 81 EC CC 00 00 00 sub esp,0CCh

      可知该虚表指向类B中的实现。

      五、虚继承父类,子类为空

    #include <cstdio>
    
    class A
    {
    public:
        int a;
    };
    
    class B: virtual public A
    {
    public:
    };
    
    
    int main(int argc, char** argv)
    {
        printf("%d
    ", sizeof(B));
    
        B b;
        b.a = 0xaaaaaaaa;
        B* pb = &b;
        printf("%08x
    ", pb);
    }

      windows输出:

    8
    0036f810

      查看对象b内存:

    0036F810 48
    0036F811 57
    0036F812 34 01
    0036F814 AA
    0036F815 AA
    0036F816 AA
    0036F817 AA

      内存中多了0x01345748,这个是虚基类表的指针,作用于虚函数表类似后面会详细讲。查看该虚基类表:

    B::`vbtable':
    01345748 00 00
    0134574A 00 00
    0134574c 04 00
    0134574e 00 00

      虚基类表内容含义后面讲。

      六、虚继承父类包含虚函数

    #include <cstdio>
    
    class A
    {
    public:
        int a;
        virtual void vfun(){};
    };
    
    class B: virtual public A
    {
    public:
    };
    
    
    int main(int argc, char** argv)
    {
        printf("%d
    ", sizeof(B));
    
        B b;
        b.a = 0xaaaaaaaa;
        B* pb = &b;
        printf("%08x
    ", pb);
    }

      windows输出:

    12
    002efa64

      可见内存又增加了4字节。看下对象b内存:

    002EFA64 54
    002EFA65 57
    002EFA66 86 00
    002EFA68 4C
    002EFA69 57
    002EFA6A 86 00
    002EFA6C AA
    002EFA6D AA
    002EFA6E AA
    002EFA6F AA

      有两个指针,分别为虚基类表和虚函数表:

    B::`vftable':
    0086574C 22 11
    0086574E 86 00
    00865750 00 00
    00865752 00 00
    B::`vbtable':
    00865754 00 00
    00865756 00 00

      此例中子类未实现虚函数。子类实现虚函数与四类似,只是这里多了个虚基类表,就不详细讲了。

  • 相关阅读:
    【操作系统】主存空间的分配和回收
    学术诚信与职业道德
    读《构建之法》第 8、9、10 章有感
    操作系统第三次作业
    sprint
    软件工程学期总结
    实验四 主存空间的分配和回收
    第二个冲刺
    Scrum项目6.0 和8910章读后感
    Spring 计划 7.0
  • 原文地址:https://www.cnblogs.com/budapeng/p/3305588.html
Copyright © 2011-2022 走看看