成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

詳細介紹c++中的類對象內存模型

開發 后端
在C或C++中, 可以利用不同操作平臺下的內存模型來編寫并發程序.本文詳細介紹了C++類對象的內存模型,希望對你有幫助,一起來看。

內存模型描述的是程序中各變量(實例域、靜態域和數組元素)之間的關系,以及在實際計算機系統中將變量存儲到內存和從內存取出變量這樣的低層細節.不同平臺間的處理器架構將直接影響內存模型的結構.

首先介紹一下C++中有繼承關系的類對象內存的布局:

在C++中,如果類中有虛函數,那么它就會有一個虛函數表的指針__vfptr,在類對象最開始的內存數據中。之后是類中的成員變量的內存數據。

對于子類,最開始的內存數據記錄著父類對象的拷貝(包括父類虛函數表指針和成員變量)。之后是子類自己的成員變量數據。

對于子類的子類,也是同樣的原理。但是無論繼承了多少個子類,對象中始終只有一個虛函數表指針。

虛函數表指針

為了探討C++類對象的內存布局,先來寫幾個類和函數

首先寫一個基類:

  1. class Base   
  2. {   
  3. public:   
  4. virtual void f() { cout << "Base::f" << endl; }   
  5. virtual void g() { cout << "Base::g" << endl; }   
  6. virtual void h() { cout << "Base::h" << endl; }   
  7. int base;   
  8. protected:   
  9. private:   
  10. };  

然后,我們多種不同的繼承情況來研究子類的內存對象結構。

1. 無虛函數集繼承

  1. //子類1,無虛函數重載   
  2. class Child1 : public Base   
  3. {   
  4. public:   
  5. virtual void f1() { cout << "Child1::f1" << endl; }   
  6. virtual void g1() { cout << "Child1::g1" << endl; }   
  7. virtual void h1() { cout << "Child1::h1" << endl; }   
  8. int child1;   
  9. protected:   
  10. private:   
  11. };   

這個子類Child1沒有繼承任何一個基類的虛函數,因此它的虛函數表如下圖:

Child1的虛函數表

我們可以看出,子類的虛函數表中,先存放基類的虛函數,在存放子類自己的虛函數。

2. 有一個虛函數繼承

  1. //子類2,有1個虛函數重載   
  2. class Child2 : public Base   
  3. {   
  4. public:   
  5. virtual void f() { cout << "Child2::f" << endl; }   
  6. virtual void g2() { cout << "Child2::g2" << endl; }   
  7. virtual void h2() { cout << "Child2::h2" << endl; }   
  8. int child2;   
  9. protected:   
  10. private:   
  11. };  

Child2的虛函數表

當子類重載了父類的虛函數,則編譯器會將子類虛函數表中對應的父類的虛函數替換成子類的函數。

3. 全部虛函數都繼承

  1. //子類3,全部虛函數重載   
  2. class Child3 : public Base   
  3. {   
  4. public:   
  5. virtual void f() { cout << "Child3::f" << endl; }   
  6. virtual void g() { cout << "Child3::g" << endl; }   
  7. virtual void h() { cout << "Child3::h" << endl; }   
  8. protected:   
  9. int x;   
  10. private:   
  11. };  

Child3的虛函數表

#p#

4. 多重繼承

多重繼承,即類有多個父類,這種情況下的子類的內存結構和單一繼承有所不同。

子類的內存結構

我們可以看到,當子類繼承了多個父類,那么子類的內存結構是這樣的:

子類的內存中,順序

子類內存的順序

5. 菱形繼承

菱形繼承


6. 單一虛擬繼承

單一虛擬繼承

虛擬繼承的子類的內存結構,和普通繼承完全不同。虛擬繼承的子類,有單獨的虛函數表, 另外也單獨保存一份父類的虛函數表,兩部分之間用一個四個字節的0x00000000來作為分界。子類的內存中,首先是自己的虛函數表,然后是子類的數據成員,然后是0x0,之后就是父類的虛函數表,之后是父類的數據成員。

如果子類沒有自己的虛函數,那么子類就不會有虛函數表,但是子類數據和父類數據之間,還是需要0x0來間隔。
因此,在虛擬繼承中,子類和父類的數據,是完全間隔的,先存放子類自己的虛函數表和數據,中間以0x分界,最后保存父類的虛函數和數據。如果子類重載了父類的虛函數,那么則將子類內存中父類虛函數表的相應函數替換。

7. 菱形虛擬繼承

菱形虛擬繼承

結論:

(1) 對于基類,如果有虛函數,那么先存放虛函數表指針,然后存放自己的數據成員;如果沒有虛函數,那么直接存放數據成員。

(2) 對于單一繼承的類對象,先存放父類的數據拷貝(包括虛函數表指針),然后是本類的數據。

(3) 虛函數表中,先存放父類的虛函數,再存放子類的虛函數

(4) 如果重載了父類的某些虛函數,那么新的虛函數將虛函數表中父類的這些虛函數覆蓋。

(5) 對于多重繼承,先存放第一個父類的數據拷貝,在存放第二個父類的數據拷貝,一次類推,最后存放自己的數據成員。其中每一個父類拷貝都包含一個虛函數表指針。如果子類重載了某個父類的某個虛函數,那么該將該父類虛函數表的函數覆蓋。另外,子類自己的虛函數,存儲于第一個父類的虛函數表后邊部分。

(6) 當對象的虛函數被調用是,編譯器去查詢對象的虛函數表,找到該函數,然后調用。

到這c++類對象的內存模型就介紹完了,希望對大家有幫助。

【編輯推薦】

  1. 使用托管C++粘合C#和C++代碼(一)
  2. 談談C++中三個容易混淆的概念
  3. C/C++是程序員必須掌握的語言嗎?
  4. VC++獲得當前系統時間的幾種方案
  5. C++連接mysql數據庫的兩種方法
責任編輯:于鐵 來源: 互聯網
相關推薦

2010-01-18 17:48:46

C++類對象

2011-07-20 13:40:09

拷貝構造函數

2011-07-20 15:58:53

C++引用

2010-01-19 18:51:17

C++類

2010-01-25 14:56:08

C++程序

2011-07-20 17:16:50

C++重載函數

2011-07-15 13:49:30

C++友元函數友元類

2011-07-13 16:49:59

C++

2010-03-24 12:45:00

Python 嵌入

2011-07-20 13:57:06

C++STL

2010-01-15 18:35:25

C++的類

2011-07-14 16:56:21

2011-07-14 23:27:05

C++引用

2011-06-21 10:37:56

const

2011-07-14 16:26:01

2011-07-20 16:43:34

C++

2011-07-20 16:48:22

C++static

2011-07-20 16:57:05

C++const

2011-07-20 16:50:39

inlinec++

2010-01-19 13:17:05

C++數據類型
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人精品福利 | 一二三四在线视频观看社区 | 国产精品久久久久久久粉嫩 | 91超碰在线 | 毛片毛片毛片毛片毛片 | 欧美在线视频一区 | 亚洲区一区二区 | 免费黄色网址视频 | 日韩一区二区三区av | 亚洲一区二区中文字幕 | 亚洲1区| 国产成人精品福利 | 国产亚洲精品久久久久久牛牛 | 久久逼逼| 国产综合久久 | 精品一区二区在线看 | 粉嫩高清一区二区三区 | 久久与欧美 | 成人av免费 | av中文在线 | 中文字幕一区二区视频 | 日日欧美 | 日本不卡一区二区三区在线观看 | 精品欧美一区二区三区精品久久 | 国产精品久久久久久久久久久久 | 欧美日韩精品专区 | 国产日韩视频在线 | 久久人人国产 | 99精品一区二区三区 | 放个毛片看看 | 一本在线 | 日韩中文在线视频 | 日日操夜夜操天天操 | 国产免费a| 日本高清在线一区 | 国产男人的天堂 | 欧美日韩专区 | 亚洲欧洲色视频 | 九九热视频这里只有精品 | 国产精品亚洲精品久久 | 亚洲一区二区中文字幕 |