自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳細(xì)介紹c++中的類對象內(nèi)存模型

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

內(nèi)存模型描述的是程序中各變量(實例域、靜態(tài)域和數(shù)組元素)之間的關(guān)系,以及在實際計算機系統(tǒng)中將變量存儲到內(nèi)存和從內(nèi)存取出變量這樣的低層細(xì)節(jié).不同平臺間的處理器架構(gòu)將直接影響內(nèi)存模型的結(jié)構(gòu).

首先介紹一下C++中有繼承關(guān)系的類對象內(nèi)存的布局:

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

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

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

虛函數(shù)表指針

為了探討C++類對象的內(nèi)存布局,先來寫幾個類和函數(shù)

首先寫一個基類:

  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. };  

然后,我們多種不同的繼承情況來研究子類的內(nèi)存對象結(jié)構(gòu)。

1. 無虛函數(shù)集繼承

  1. //子類1,無虛函數(shù)重載   
  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沒有繼承任何一個基類的虛函數(shù),因此它的虛函數(shù)表如下圖:

Child1的虛函數(shù)表

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

2. 有一個虛函數(shù)繼承

  1. //子類2,有1個虛函數(shù)重載   
  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的虛函數(shù)表

當(dāng)子類重載了父類的虛函數(shù),則編譯器會將子類虛函數(shù)表中對應(yīng)的父類的虛函數(shù)替換成子類的函數(shù)。

3. 全部虛函數(shù)都繼承

  1. //子類3,全部虛函數(shù)重載   
  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的虛函數(shù)表

#p#

4. 多重繼承

多重繼承,即類有多個父類,這種情況下的子類的內(nèi)存結(jié)構(gòu)和單一繼承有所不同。

子類的內(nèi)存結(jié)構(gòu)

我們可以看到,當(dāng)子類繼承了多個父類,那么子類的內(nèi)存結(jié)構(gòu)是這樣的:

子類的內(nèi)存中,順序

子類內(nèi)存的順序

5. 菱形繼承

菱形繼承


6. 單一虛擬繼承

單一虛擬繼承

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

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

7. 菱形虛擬繼承

菱形虛擬繼承

結(jié)論:

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

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

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

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

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

(6) 當(dāng)對象的虛函數(shù)被調(diào)用是,編譯器去查詢對象的虛函數(shù)表,找到該函數(shù),然后調(diào)用。

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

【編輯推薦】

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

2010-01-18 17:48:46

C++類對象

2011-07-20 13:40:09

拷貝構(gòu)造函數(shù)

2011-07-20 15:58:53

C++引用

2010-01-19 18:51:17

C++類

2010-01-25 14:56:08

C++程序

2011-07-15 13:49:30

C++友元函數(shù)友元類

2011-07-20 17:16:50

C++重載函數(shù)

2010-03-24 12:45:00

Python 嵌入

2011-07-13 16:49:59

C++

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-07-14 16:26:01

2011-07-20 16:43:34

C++

2011-06-21 10:37:56

const

2011-07-20 16:50:39

inlinec++

2011-07-20 16:48:22

C++static

2011-07-20 16:57:05

C++const

2011-07-13 11:12:43

C++MFC
點贊
收藏

51CTO技術(shù)棧公眾號