zoukankan      html  css  js  c++  java
  • C++类的内存结构

    摘自Jerry19880126

    简单类

    class Base
    {
        int a;
        int b;
    public:
        void CommonFunction();
    };
    

    简单类继承

    class DerivedClass: public Base
    {
        int c;
    public:
        void DerivedCommonFunction();
    };
    

    带有虚函数的类

    class Base
    {
        int a;
        int b;
    public:
        void CommonFunction();
        void virtual VirtualFunction();
    };
    

    虚函数类继承

    没有复写的继承

     class DerivedClass: public Base
    {
        int c;
    public:
        void DerivedCommonFunction();
        void virtual VirtualFunction();
    };
    

    复写的继承

    class DerivedClass1 : public Base
    {
        int c;
    public:
        void DerivedCommonFunction();
        void virtual VirtualFunction();
        void virtual VirtualFunction2();
    };
    

    多重继承

    class Base
    {
        int a;
        int b;
    public:
        void CommonFunction();
        void virtual VirtualFunction();
    };
    
    
    class DerivedClass1: public Base
    {
        int c;
    public:
        void DerivedCommonFunction();
        void virtual VirtualFunction();
    };
    
    class DerivedClass2 : public Base
    {
        int d;
    public:
        void DerivedCommonFunction();
        void virtual VirtualFunction();
    };
    
    class DerivedDerivedClass : public DerivedClass1, public DerivedClass2
    {
        int e;
    public:
        void DerivedDerivedCommonFunction();
        void virtual VirtualFunction();
    };
    

    内存分布从父类到子类,依次如下:
    Base中有一个虚表指针

    DerivedClass1继承了Base,内存排布是先父类后子类。

    DerivedClass2的情况是类似于DerivedClass1的。

    DerivedDerivedClass,由外向内看,它并列地排布着继承而来的两个父类DerivedClass1与DerivedClass2,还有自身的成员变量e。DerivedClass1包含了它的成员变量c,以及Base,Base有一个0地址偏移的虚表指针,然后是成员变量a和b;DerivedClass2的内存排布类似于DerivedClass1,注意到DerivedClass2里面竟然也有一份Base。

    这里有两份虚表了,分别针对DerivedClass1与DerivedClass2,在&DerivedDericedClass_meta下方的数字是首地址偏移量,靠下面的虚表的那个-16表示指向这个虚表的虚指针的内存偏移,这正是DerivedClass2中的{vfptr}在DerivedDerivedClass的内存偏移。

    虚继承

    class DerivedClass1: virtual public Base
    {
        int c;
    public:
        void DerivedCommonFunction();
        void virtual VirtualFunction();
    };
    
    class DerivedClass2 : virtual public Base
    {
        int d;
    public:
        void DerivedCommonFunction();
        void virtual VirtualFunction();
    };
    
    class DerivedDerivedClass :  public DerivedClass1, public DerivedClass2
    {
        int e;
    public:
        void DerivedDerivedCommonFunction();
        void virtual VirtualFunction();
    };
    

    Base类没有变化

    DerivedClass1就已经有变化了,原来是先排虚表指针与Base成员变量,vfptr位于0地址偏移处;但现在有两个虚表指针了,一个是vbptr,另一个是vfptr。vbptr是这个DerivedClass1对应的虚表指针,它指向DerivedClass1的虚表vbtable,另一个vfptr是虚基类表对应的虚指针,它指向vftable。

    下面列出了两张虚表,第一张表是vbptr指向的表,8表示{vbptr}与{vfptr}的偏移;第二张表是vfptr指向的表,-8指明了这张表所对应的虚指针位于内存的偏移量。

    DerivedClass2的内存分布类似于DerivedClass1,同样会有两个虚指针,分别指向两张虚表(第二张是虚基类表)。

    下面来仔细看一下DerivedDerivedClass的内存分布,这里面有三个虚指针了,但base却只有一份。第一张虚表是内含DerivedClass1的,20表示它的虚指针{vbptr}离虚基表指针{vfptr}的距离,第二张虚表是内含DerivedClass2的,12表示它的虚指针{vbptr}离虚基表指针{vfptr}的距离,最后一张表是虚基表,-20指明了它对应的虚指针{vfptr}在内存中的偏移。


    虚继承的作用是减少了对基类的重复,代价是增加了虚表指针的负担(更多的虚表指针)。

    下面总结一下(当基类有虚函数时):

    1. 每个类都有虚指针(vptr, virtual table pointer)和虚函数表(vtbl, virtual table); 2. 如果不是虚继承,那么子类将父类的虚指针继承下来,并指向自身的虚函数表(发生在对象构造时)。有多少个虚函数,虚函数表里面的项就会有多少。多重继承时,可能存在多个的基类虚函数表与虚指针; 3. 如果是虚继承,那么子类会有两份虚指针,一份指向自己的虚函数表,另一份指向基类虚函数表,多重继承时基类虚函数表与基类虚指针有且只有一份。
  • 相关阅读:
    ios 正则表达式
    2016/2/26 jQuery的技术 1,安装 2,语法选择器$ 事件触发 3,常用jQuery函数
    2016/2/26 <marquee></marquee>实现多种滚动效果
    2016/2/25 onchange 应用
    2016/2/25 1、<表单验证<form></form> 2、正则表达式 3、事件
    2016/2/25 1, margin auto 垂直方向测试 无效 2,margin重叠 3,哪些是块状哪些是内联 4,display:block inline 导航栏把内联转块状最常见+ 扩展
    2016/2/25 html+css学习资源
    2016/2/24 css画三角形 border的上右下左的调整 以及内区域的无限变小 边界透明
    2016/2/24 1,css有几种引入方式 2,div除了可以声明id来控制,还可以声明什么控制? 3,如何让2个div,并排显示。4,清除浮动 clear:left / right / both
    2016/2/24 1,dotctype有几种? 2,了解html的发展历史
  • 原文地址:https://www.cnblogs.com/narjaja/p/10067996.html
Copyright © 2011-2022 走看看