之前在使用指標的時候,常常對指標的型別感到困惑,既然所有的指標都只佔4個位元組,那麼他所對應的指標型別在指標轉化過程中有什麼作用呢。最近,終於弄懂了他們的關係,相關說明如下:
1.前提首先定義了乙個zooanimal類如下:
class zooanimal;
2.說明定義如下三個指標:
zooanimal *px;
int *pi;
array*pta;
以記憶體需求的觀點來說,沒什麼不同,他們三個都需要有足夠的記憶體來放置乙個機器位址(32位機器上是4位元組)。「指向不同型別之各指標」間的差異,既不在於其指標的表示不同,也不在其內容不同,而是在其所定址出來的object型別不同。也就是說,「指標型別」會教導編譯器如何解釋某個特定位址中的記憶體及其大小:
1.乙個指向位址1000的整數指標,在32位機器上,將涵蓋位址空間1000--1003.
2.如果string是傳統的8-bytes(包括乙個 4-bytes的字元指標和乙個用來表示字串長度的整數),那麼乙個zooanimal指標將橫跨位址空間1000--1015。如下圖所示:
乙個指向位址1000而型別為void*的指標,將涵蓋怎樣的位址空間呢?是的,我們不知道!這就是為什麼乙個,型別為void *的指標只能夠含有乙個位址,而不能夠通過它操作所指之object的緣故。
所以,轉型(cast)其實是一種編譯器指令,大部分情況下它並不改變乙個指標所含的真正位址,它只影響「被指出之記憶體的大小和其內容」的解釋方式。
3.加上多型之後
現在,讓我們定義乙個bear,作為一種zooanimal。當然,經由"public 繼承"可以完成這件任務:
class bear:public zooanimal;
dances dances_known;
int cell_block;
};bear b("yogi");
bear *pb=&b;
bear &rb=*pb;
b,pb,rb 會有怎樣的記憶體需求呢?不管是pointer或reference都只需要乙個word的空間(在32位機器上是4-bytes)。bear object需要24bytes,也就是zooanimal的16bytes加上bear所帶來的8bytes。下圖展示了可能的記憶體布局:
好,假設我們的bear object 放在位址1000處,乙個bear指標和乙個zooanimal指標有什麼不同?
bear b;
zooanimal *pz=&bl;
bear *pb=&b;
它們每個都指向bear object 的第乙個byte。其間的差別是,pb所涵蓋的位址包含整個bear object,而pz所涵蓋的位址只包含bear object中的zooanimal subobject。
除了zooanimal subobject 中出現的members,你不能夠實用pz來直接處理bear的任何menbers。唯一例外是通過virtual機制:
//不合法:cell_back不是zooanimal的乙個member,雖然我們知道pz當前指向乙個 bear object。
pz->cell_back;
//ok:經過乙個明白的downcast操作就沒有問題 !
((bear *)pz)->cell_block;
//下面這樣更好,但是它是乙個run-time operation (成本較高)
if(bear *pb2=dynamic_cast(pz))
pb2->cell_block;
//ok,因為cell_block是bear 的乙個member。
pb->cell_block;
當我們寫:
pz->rotate();
時,pz的型別將在編譯時期決定以下兩點:
1.固定的可用介面。也就是說,pz只能夠呼叫zooanimal的public 介面。
2.該介面的access level(例如rotate()是zooanimal的乙個public member)。
在每乙個執行點,pz所指的object型別可用決定rotate()所呼叫的實體,型別資訊的封裝並不是維護於pz之中,而是維護於link之中,此link存在於「object 的vptr」和「vptr 所指之virtual table之間」
另外,c++的多型就是通過指標和引用實現的,例如:
bear b;
zooanimal za=b;
//呼叫zooanimal::rotate()
za.rotate();
在以上**中,使用bear型別物件初始化zooanimal物件,必然會對bear型別物件進行裁剪,只是保留跟zooanimal有關的資訊。所以za.rotate()必然是呼叫zooanimal中的rotate(),所以多型不能夠在"直接訪問objects"上發揮作用。
《深度探索c++物件模型》
C 指標使用方法解惑
在下列函式宣告中,為什麼要同時使用 和 符號?以及什麼場合使用這種宣告方式?void func1 myclass pbuildingelement 論壇中經常有人問到這樣的問題。本文試圖通過一些實際的指標使用經驗來解釋這個問題。仔 細看一下這種宣告方式,確實有點讓人迷惑。在某種意義上,和 是意思相對...
C語言指標問題快速解惑
1 int a 3 int p a 把陣列名賦值給指標表示將陣列的首元素的位址賦予此指標。2 int a 3 int p a 0 a 0 是a陣列的首元素,而 則是取位址運算子,所以 a 0 取得的同樣是a陣列的首元素的位址,因此這段 的含義和 段是一致的。3 char c1 hello char ...
C 指標使用方法解惑
在下列函式宣告中,為什麼要同時使用 和 符號?以及什麼場合使用這種宣告方式?void func1 myclass pbuildingelement 論壇中經常有人問到這樣的問題。本文試圖通過一些實際的指標使用經驗來解釋這個問題。仔細看一下這種宣告方式,確實有點讓人迷惑。在某種意義上,和 是意思相對的...