標籤:
好吧,我承認標題是用來搞笑的,因為內容實在談不上有什麼深度,只是介紹下記憶體布局,深度不夠只好淺度來湊:-)
單刀直入,這次部落格計劃討論如下三種情形下的C++對象記憶體布局:
1.單繼承帶覆蓋;
2.帶重複繼承的多重繼承帶覆蓋;
3.帶重複繼承的多重虛擬繼承帶覆蓋
之所以只給出這三種情況是因為個人認為其餘的情形是平凡的,被以上三種所蘊含;其次這幾種情況都是包含成員變數的,這也是和上篇部落格的區別所在;最後就是這篇決定調整一下敘述方式:先給出預期結果,然後通過運行結果來驗證我們的想法。
以下程式運行環境均是32位WIN7系統 + Visual Studio 2010。
一、單繼承帶覆蓋:
先上代碼:
1 #include <iostream> 2 using namespace std; 3 4 //單繼承帶覆蓋有資料成員和成員函數的情況下記憶體布局 5 class Base{ 6 7 public: 8 Base():_base(10){} 9 virtual void f(){ cout<<"Base::f()"<<endl; }10 private:11 int _base;12 };13 14 class Derive: public Base{15 16 public:17 Derive():_derive(100){}18 virtual void f(){ cout<<"Derive::f()"<<endl;}19 virtual void g(){ cout<<"Derive::g()"<<endl;}20 private:21 int _derive;22 };23 24 class DDerive: public Derive{25 26 public:27 DDerive():_dderive(1000){}28 virtual void f(){ cout<<"DDerive::f()"<<endl;}29 virtual void g(){ cout<<"DDerive::g()"<<endl;}30 virtual void h(){ cout<<"DDerive::h()"<<endl;}31 private:32 int _dderive;33 };34 35 int main(){36 37 DDerive d;38 typedef void (*Fun)();39 Fun pFun = NULL;40 //首先通過函數指標調用成員函數41 pFun = (Fun)*((int*)*((int*)(&d) + 0) + 0);42 pFun();43 pFun = (Fun)*((int*)*((int*)(&d) + 0) + 1);44 pFun();45 pFun = (Fun)*((int*)*((int*)(&d) + 0) + 2);46 pFun();47 //再通過函數指標訪問衍生類別中的資料成員:48 cout<<"Base::_base = " <<*(int*)((int*)(&d) + 1)<<endl;49 cout<<"Derive::_derive = " <<*(int*)((int*)(&d) + 2)<<endl;50 cout<<"DDerive::_dderive = "<<*(int*)((int*)(&d) + 3)<<endl;51 52 getchar();53 return 0;54 }View Code
預期記憶體布局圖示如下:
運行結果為:
可以看到,運行結果和預期完全一致。
二、帶重複繼承的多重繼承帶覆蓋:
三、帶重複繼承的多重虛擬繼承帶覆蓋:
淺度探索C++物件模型