前段時間在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...