基礎知識:
ø陣列:在
c/c++
中,陣列是一塊連續的記憶體,記憶體中陣列元素緊密地排列在一起。記憶體的大小
= 元素個數
x 單個元素的大小。
ø操作符
:使用索引訪問資料中的元素。元素在記憶體中的位置為:陣列開始位置
+ 索引
x單個元素的大小。
ø類的例項
:類的例項也占用記憶體。類佔記憶體的大小和類的資料成員有關,類的資料成員越多,那麼占用的記憶體也越大。
ø子類和父類的記憶體分配:父類中的資料成員在前,子類的資料成員在後。
ø指標的加減法:當指標加減乙個整數時,實際的指標位置加減量為:該整數
* 指向型別的大小。如
int *p; p+1
的結果是
p指向位置後的第
4個位元組。
ødelete
:刪除資料。從指標位置開始刪除陣列元素,一直到記憶體塊結束。對於類陣列,會對每個元素呼叫析構函式。
子類陣列:
基於以上知識,子類陣列的記憶體分布可以粗略表示為下圖:
使用父類指標時的操作分析:
把乙個子類陣列變數賦值給乙個資料元素父類的指標時,指標首先指向陣列頭的位置(如圖)。操作1
:訪問元素
訪問第乙個元素(元素
0)時,沒有任何問題。
訪問下乙個元素時,指標後移。按正常用法使用
++操作或
+=1操作。因為該指標是父類指標,所以偏移量為父類的大小
sizeof(父類)
。這時指標將指向圖中「子類資料」的位置,而不是元素
1的位置。這將導致出錯。使用
操作訪問時也有同樣的問題。操作2
:使用delete
刪除資料:
delete
同樣是按訪問元素的方法逐個析構這些元素。因為它無法找到物件真正的起始位置。
特殊情況:
在csdn
的討論中,有人寫出了驗證**,證明這樣訪問沒有問題,如
的**:
#include
<
iostream.h
>
class
base
virtual
~base()
};class
child:
public
base
virtual
~child()
};int
main(
intargc,
char
*argv)
這段**可以正確執行,但與剛才所說的並不矛盾。這段**中的
child
類屬於特例,因為它沒有資料成員,子類資料是空的。這時如果使用
sizeof
來檢查child
類和base
類的大小,會發現它們是相同的。所以無論使用子類指標還是父類指標,元素定位的計算結果都一樣。
總結:
不要用父類指標去操作子類陣列,雖然你可能碰巧不出錯。
c 基類指標,子類指標,多型
基類指標和子類指標之間的相互賦值 1 將子類指標賦值給基類指標時,不需要進行強制型別轉換,c 編譯器將自動進行型別轉換。因為子類物件也是乙個基類物件。2 將基類指標賦值給子類指標時,需要進行強制型別轉換,c 編譯器將不自動進行型別轉換。因為基類物件不是乙個子類物件。子類物件的自增部分是基類不具有的。...
談談基類與子類的this指標(C )
引入定義乙個類的物件,首先系統已經給這個物件分配了空間,然後會呼叫建構函式 說明 假設存在建構函式 乙個類有多個物件,當程式中呼叫物件的某個函式時,有可能要訪問到這個物件的成員變數。而對於同乙個類的每乙個物件,都是共享同乙份類函式。物件有單獨的變數,但是沒有單獨的函式,所以當呼叫函式時,系統必須讓函...
C 基類與子類 函式指標的定義和轉換
定義乙個類,作為基類 twindow public cwnd 定義乙個字類 class tform public twindow void onbuttonclicked 定義乙個函式指標 typef void twindow functionptr 使用這個指標 functionptr fun f...