C++单一、多重继承下的内存模型

一:C++单一继承下的内存模型:

a)、最简单的一种单一继承内存模型:基类及派生类中无virtual function member:

#include <iostream>
class Base
{
public:
    Base(char _x = '\0') :m_x(_x) {}
    ~Base() {}
private:
    char m_x;
};
class Derived :public Base
{
public:
    Derived(char _x = '\0',int _y = 0,int _s = 0) :Base(_x), m_y(_y),m_z(_s) {}
    ~Derived() {}
private:
    int m_y;
    int m_z;
};
int main()
{
    Derived d('A',20,30);    
    return 0;
}

    在MSVC2015 Debug ×86下,&d = 0x00eff88c;&d.m_x = 0x00eff88c;&d.m_y = 0x00eff890;&d.m_z = 0x00eff894;至于d.m_x为什么会占用4个字节空间大小,这个跟内存对齐有关,由此可见,在单一继承下且类中non-virtual function member时,在派生类中内存模型:地址由低到高,分别为:派生类对象中基类子对象数据成员地址(顺序由基类中数据成员申明先后有关)、派生类特有对象数据成员地址(同上);

b)、单一继承下有virtual function member情况下:

#include <iostream>
class Base
{
public:
    Base(char _x = '\0') :m_x(_x) {}
    virtual void Show() { std::cout<<"this is BaseClass"<<std::endl; }
    ~Base() {}
private:
    char m_x;
};
class Derived :public Base
{
public:
    Derived(char _x = '\0',int _y = 0,int _s = 0) :Base(_x), m_y(_y),m_z(_s) {  }
    virtual void Show() { std::cout << "this is Derived" << std::endl; }
    ~Derived() {}
private:
    int m_y;
    int m_z;
};
int main()
{
    Derived d('A',20,30);    
    return 0;
}

同样是在上述环境下,取&d = 0x0133f730;&d.m_x = 0x00133f734;&d.m_y = 0x00133f738;&d.m_z = 0x00133f73c;发现&d!=&d.m_x,这是由于在这四个字节的内存空间当中,存放了指向virtual function table(此为一列表格(可将其理解为数组),此表格中存放的是类中virtual function地址,vptr指向第一个在类中申明的virtual地址)的地址vptr;由此可以看到,在单继承模型中,派生类对象的内存模型:地址由低到高,分别为:vptr所指向的地址,派生类对象中基类子对象数据成员地址(顺序由基类中数据成员申明先后有关)、派生类特有对象数据成员地址(同上);

二:C++多重继承下的内存模型:

这也是C++与其他Object-Oriented编程语言如:java,C#的一个很大的不同,在java和C#当中取消了多重继承,取而代之的是通过继承接口的方式实现一种多继承;

#include <iostream>
class Base1
{
public:
    Base1(char _x = '\0') :m_x(_x) {}
    virtual void Show() { std::cout<<"this is Base1Class"<<std::endl; }
    ~Base1() {}
private:
    char m_x;
};
class Base2
{
public:
    Base2(int _a = 0):m_a(_a) {}
    virtual void display() { std::cout << "this is Base2Class" << std::endl; }
private:
    int m_a;
};
class Derived :public Base1,Base2
{
public:
    Derived(char _x = '\0',int _a = 0,int _y = 0,int _s = 0) :Base1(_x), Base2(_a),m_y(_y),m_z(_s) {  }
    virtual void Show() { std::cout << "this is Derived inherited by Base1" << std::endl; }
    virtual void display() { std::cout << "this is Dervied inherited by Base2" << std::endl; }
    ~Derived() {}
private:
    int m_y;
    int m_z;
};
int main()
{
    Derived d('A',10,20,30);    
    return 0;
}

内存地址分布如下:

此时可以看到,在派生类对象模型中,地址由低到高,分别为:在继承申明时,派生类中第一个基类子对象的vptr,派生类中第一个基类子对象的地址;派生类中第二个基类子对象的vptr,派生类中第二个基类子对象的地址....由此进行类推;

总结:从上述分析可知,在派生类对象的内存模型当中,地址从低到高,分别为:基类当中vptr所指向的地址-->派生类中基类子对象地址-->派生类vptr所指向的地址-->派生类中特有对象的地址:

值得一提的是在发生类似于菱形继承时,通过virtual 继承方式,对象的内存模型会更加复杂;

猜你喜欢

转载自www.cnblogs.com/xin-99/p/9495909.html