標籤:image splay 繼承 ... his 最簡 inf UNC vat
一: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 繼承方式,對象的記憶體模型會更加複雜;
C++單一、多重繼承下的記憶體模型