從記憶體上解析c 中陣列為什麼不支援多型

2021-08-27 15:47:27 字數 2593 閱讀 5159

前段時間在c/c++版塊的時候,看到有人問為什麼陣列物件不支援多型的問題,當時沒有回,只是感覺不支援!不能拿出理論和實際證據!後面因為工作也就沒有

細想,今天剛好看到酷殼上陳皓老師說的也就來述說一下!

因為這個涉及到記憶體的問題,所以 我們先來乙個小段c語言簡單**

typedef struct 

base_t;

typedef struct

derived_t;

int main(void)

,

};

base_t *pa = (base_t *)stb;

// base_t *pa = (base_t *)malloc(2 * sizeof(base_t));

// pa[0].ptrv = (void*)0x3;

// pa[0].a = 1000;

// pa[0].c = 'a';

//// pa[1].ptrv = (void*)0x4;

// pa[1].a = 2000;

// pa[1].c = 'a';

// derived_t *pb = (derived_t *)pa;

return 0;

}

通過gdb除錯看到棧上的資料情況

(gdb) p stb

$4 = , }

(gdb) p pa[0]

$5 =

(gdb) p pa[1]

$6 =

(gdb) q

a debugging session is active.

很明顯,pa[0]的還是正確,但是pa[1]的值已經完全被破壞掉了!

上面的例子已經能說明乙個部分的原因了,我們再改把main函式裡面注釋開啟,把上面的注釋掉再看看

int main(void)

, //

// };

// base_t *pa = (base_t *)stb;

base_t *pa = (base_t *)malloc(2 * sizeof(base_t));

pa[0].ptrv = (void*)0x3;

pa[0].a = 1000;

pa[0].c = 'a';

pa[1].ptrv = (void*)0x4;

pa[1].a = 2000;

pa[1].c = 'a';

derived_t *pb = (derived_t *)pa;

return 0;

}

gdb除錯結果如下:

(gdb) n

53 return 0;

(gdb) p pa[0]

$1 =

(gdb) p pa[1]

$2 =

(gdb) p pb[0]

$3 =

(gdb) p pb[1]

$4 =

(gdb) p pb[1]

$4 =

很明顯,pb[1]的值,也完全被破壞了!

可見,這完全就是c語言裡亂轉型造成了記憶體的混亂,這和c++一點關係都沒有。

而且,c++的任何一本書都說過,父類物件和子類物件的轉型會帶來嚴重的記憶體問題。

那我們接下來看看c++的例程:

#include using namespace std;

class base

{ public:

int b;

virtual ~base()

{

cout <<"base::~base()"<

在子類中,注釋 int d 執行結果如下:

size base    = 8

size derived = 8

derived::derived~()

base::~base()

derived::derived~()

base::~base()

不注釋 int d 執行結果如下:

size base    = 8

size derived = 12

segmentation fault

上面的**可以正確執行,包括呼叫子類的虛函式!因為記憶體對齊了。

但是如果開啟遮蔽的int成員的話,這個程式就segmentation fault了。

pb[1]的虛表找到了乙個錯誤的記憶體上,記憶體亂掉了。

所以通過上面的乙個c語言的基本例程和乙個c++的例程,大家就可以完全理解為什麼c++中陣列不支援多型了吧!

從記憶體這邊來分析,這個完全就是c語言的記憶體管理知識,和c++語言本身一點關係都沒有的,如果對c語言記憶體管理這塊熟悉的話,

一眼就知道內存在其中作祟了!所以從c++很多東西也可以看出,c語言確實比較強大!學好了它,其他語言都容易融會貫通了!

C 為什麼不支援某些東西

1 學習c 的過程,經常發現c 不支援一些東西,思考下,為什麼?2 c 不支援一些東西,有兩個原因 a 可以做到,但是會導致一些不合理的結果,這些結果往往與程式設計師的期望不一致。b 屬於 臣妾做不到啊 3 對於第一種情況,比如 a 傳引用,存在隱式型別轉換,會建立乙個臨時物件。對引用的修改,不能體...

為什麼這麼多的部落格不支援Live Writer?

前兩天安裝了live writer 感覺很興奮,因為它可以離線的去寫日誌,一直想體驗一下,live writer是微軟的產品,所以對live spaces的支援很好,但同時也支援其他型別的blog,只要開放了對應的api,我不是乙個不懂程式設計的人,所以對那些東西不懂。為了體驗一下這個強大的工具,這...

為什麼C 支援函式過載而C語言不支援?

gcc和g 編譯的過程類似,細節處理不一樣 list.h list.c test.c 1.預處理 標頭檔案的展開 巨集替換 條件編譯 去掉注釋 list.i test.i 2.編譯 檢查語法錯誤 生成彙編 list.s test.s 3.彙編 將彙編 轉換成對應的機器 list.o test.o 4...