一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - 淺談C++中派生類對象的內存布局

淺談C++中派生類對象的內存布局

2021-04-22 15:28C++教程網 C/C++

下面小編就為大家帶來一篇淺談C++中派生類對象的內存布局。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

主要從三個方面來講:

  1 單一繼承

  2 多重繼承

  3 虛擬繼承

1 單一繼承

(1)派生類完全擁有基類的內存布局,并保證其完整性。

派生類可以看作是完整的基類的Object再加上派生類自己的Object。如果基類中沒有虛成員函數,那么派生類與具有相同功能的非派生類將不帶來任何性能上的差異。另外,一定要保證基類的完整性。實際內存布局由編譯器自己決定,VS里,把虛指針放在最前邊,接著是基類的Object,最后是派生類自己的object。舉個栗子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A
{
  int b;
  char c;
};
class A1 :public A
{
    char a;
};
int main()
{
  cout << sizeof(A) << " " << sizeof(A1) << endl;
  return 0;
}

輸出是什么?

答案:

8 12

A類的話,一個int,一個char,5B,內存對齊一下,8B。A1的話,一個int,兩個char,內存對齊一下,也是8B。不對嗎?

我說了,要保證基類對象的完整性。那么一定要保證A1類前面的幾個字節一定要與A類完全一樣。也就是說,A類作為內存補齊的3個字節也是要出現在A1里面的。也就是說,A類是這樣的:int(4B)+char(1B)+padding(3B)=8B,A1類:int(4B)+char(1B)+padding(3B)+char(1B)+padding(3B)=12B。

(2)虛指針怎么處理?

還是視編譯器而定,VS是永遠把vptr放在對象的最前邊。如果基類中含有虛函數,那么處理情況與上邊一樣。可是,如果基類中沒有虛函數而派生類有的話,那么如果把vptr放在派生類的前邊的話,將會導致派生類中基類成分并不在最前邊。這將帶來什么問題呢?舉栗:假設A不含虛,而A1含。

?
1
2
3
A *pA;
A1 obj_A1;
pA=&obj_A1;

如果A1完全包含A并且A位于A1的最前邊,那么編譯器只需要把&obj_A1直接賦給pA就可以了。如果不是呢?編譯器就需要把&obj_A1+sizeof(vptr)賦給pA了。

2 多重繼承

說結論:VS的內存布局是按照聲明順序排列內存。再舉個栗子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class point2d
{
public:
  virtual ~point2d(){};
  float x;
  float y;
};
class point3d :public point2d
{
  ~point3d(){};
  float z;
};
class vertex
{
public:
  virtual ~vertex(){};
  vertex* next;
};
class vertex3d :public point3d, public vertex
{
  float bulabula;
};
 
 
int _tmain(int argc, _TCHAR* argv[])
{
  cout << sizeof(point2d) << " " << sizeof(point3d) << " " << sizeof(vertex) << " " << sizeof(vertex3d) << endl;
  return 0;
}

輸出: 12 16 8 24。

內存布局:

point2d: vptr(4)+x(4)+y(4)=12B

point3d: vptr+x+y+z=16B

vertex: vptr+next=8B

vertex3d: vptr+x+y+z+vptr+next+bulabula=28B

為什么需要多個虛指針?請往下看。

3 虛擬繼承

(1)為什么要有“虛繼承”這樣的機制?

簡單講,虛繼承是為也防止“diamond”繼承所帶來的問題。也就是類A1、A2都繼承于A,類B又同時繼承于A1、A2。這樣一來,類B中就有兩份類A的成員了,這樣的程序無法通過編譯。我們改成這樣的形式:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class A
{
public:
  int a;
  virtual ~A();
  virtual void fun(){cout<<"A"<<endl;}
};
class A1 :public virtual A
{
public:
  int a1;
  virtual void fun(){cout<<"A1"<<endl;}
};
class A2 :public virtual A
{
public:
  int a2;
  virtual void fun(){cout<<"A2"<<endl;}
};
 
class B :public A1,public A2 {
public:
  int b;
  virtual void fun(){cout<<"B"<<endl;}
  virtual void funB(){};
};

這樣就能防止這樣的事情發生。

(2)虛擬繼承與普通繼承的區別:

普通繼承使得派生類每繼承一個基類便擁有一份基類的成員。而虛擬繼承會把通過虛擬繼承的那一部分,放在對象的最后。從而使得只擁有一份基類中的成員。虛擬對象的偏移量被保存在Derived類的vtbl的this指向的上一個slot。比較難理解。下面我給你個栗子。

(3)虛擬繼承的內存布局:

每個派生類會把其不變部分放在前面,共享部分放在后面。

上面四個類的大小是怎樣的呢?

?
1
2
3
4
5
int _tmain(int argc, _TCHAR* argv[])
{
  cout << sizeof(A) << " " << sizeof(A1) << " " << sizeof(A2) << " " << sizeof(B) << endl;
  return 0;
}

輸出:8 16 16 28

內存布局:

    A: vptr+a=8B

    A1: vptr+a1+vptrA+a=16B

    A2: vptr+a2+vptrA+a=16B

    A3: vptr+a1+vptrA2+a2+b+vptrA+a=28B

上個草圖:

淺談C++中派生類對象的內存布局

那究竟為什么需要多個虛指針?將對象內存布局和虛表結構搞清楚之后,答案是不是呼之欲出呢?

是的,因為這樣可以保證在將子類指針/引用轉換成基類指針時編譯器可以直接根據對像的內存布局進行偏移,從而使得指向的第一個內容為虛指針,進而實現多態(根據靜態類型執行相應動作)。

以上就是小編為大家帶來的淺談C++中派生類對象的內存布局全部內容了,希望大家多多支持服務器之家~

延伸 · 閱讀

精彩推薦
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
主站蜘蛛池模板: 久久精品人人做人人爽97 | 男人天堂a| 欧美日韩高清一区 | 国产欧美日韩视频在线观看一区二区 | 欧美精品亚洲精品日韩专区va | 四虎精品免费国产成人 | 亚洲国产精品久久网午夜小说 | 国产第一草草影院 | 91麻豆精品激情在线观看最新 | 舔比小说 | 韩国美女vip内部2020 | 亚洲国产精品无码中文字幕 | 日韩欧美高清视频 | 双性肉文h | 精品视频在线观看免费 | 久操久操久操 | 亚洲天堂成人在线观看 | 国产一区二区三区欧美精品 | 双性受合不垅腿攻np | 欧美一区二区三区视视频 | 门卫老张和女警花小说 | 夫妇野外交换激情 | 久久亚洲精品专区蓝色区 | 四虎永久成人免费 | 国产精品免费精品自在线观看 | 星星动漫在线观看无删减 | 国产成人+亚洲欧洲 | 国产男人搡女人免费视频 | 99视频导航| 国产伦精品一区二区三区免费观看 | 天天做天天爱天天一爽一毛片 | 91制片厂 果冻传媒 天美传媒 | 日本剧情片在线播放中文版 | 亚洲午夜久久久 | 韩国甜性涩爱免费观看 | 亚洲国产中文字幕在线视频综合 | 久久精品一区 | 我与旗袍老师疯狂床震 | 国产拍拍 | 婷婷99视频精品全部在线观看 | 波多野结衣伦理在线观看 |