指針的類型
創(chuàng)新互聯(lián)公司專注于網(wǎng)站建設(shè)|成都網(wǎng)站改版|優(yōu)化|托管以及網(wǎng)絡(luò)推廣,積累了大量的網(wǎng)站設(shè)計與制作經(jīng)驗,為許多企業(yè)提供了網(wǎng)站定制設(shè)計服務(wù),案例作品覆蓋航空箱等行業(yè)。能根據(jù)企業(yè)所處的行業(yè)與銷售的產(chǎn)品,結(jié)合品牌形象的塑造,量身策劃品質(zhì)網(wǎng)站。
不同類型的指針,從內(nèi)存需求的觀點來說,沒有什么不同!他們?nèi)齻€都需要足夠的內(nèi)存來繁殖一個機器地址,“指向不同類型之各指針”之間的差異,既不在其指針表示法不同,也不再其內(nèi)容(代表一個地址)不同,而是在其所尋址出來的對象類型不同。也就是說,“指針類型”會導(dǎo)致編譯器如何解釋某個特定地址中的內(nèi)存內(nèi)容及其大小
1、 一個指向地址1000的整數(shù)地址,在32位機器上,將涵蓋地址空間1000~1003
2、 那么,一個指向地址1000而類型為void*的指針,將涵蓋怎樣的地址空間呢?這個不知道,這就是為什么一個類型為void*的指針只能夠含有一個地址,而不能通過它操作所指之對象的緣故。
其實轉(zhuǎn)型是一種編譯器指令,大部分情況下它并不改變一個指針?biāo)恼嬲刂罚挥绊憽氨恢赋鲋畠?nèi)存的大小和其內(nèi)容”的解釋方式。
Class ZooAnimal{
Public:
ZooAnimal();
Virtual~ZooAnimal();
Virtualvoid rotate();
Protected:
Intloc;
Stringname;
};
Class bear:public ZooAnimal
{
Public:
Bear();
~Bear()
Voidrotate();
Viratul void dance();
Protected:
Int cell_block;
};
但是考慮多態(tài)以后呢?加入Bear繼承了ZooAnimal 同時是Public繼承
Bear b;
ZooAnimal *pz = &b;
Bear* pb = &b;
他們每個都指向Bear對象的第一個字節(jié),其間的差別是,pb所涵蓋的地址包含整個Bear對象,而pz所涵蓋的地址只包含Bear對象中的ZooAnimal子對象
除了在ZooAnimal中出現(xiàn)的成員,你不能夠?qū)嵱胮z來直接處理Bear的任何成員。唯一例外的是通過virtual機制。
Pz->cell_block;
//不正確,cell_block不是ZooAnimal的一個成員,雖然我們知道pz當(dāng)前指向一個Bear對象
((Bear*)pz)->cell_block;
//合法 經(jīng)過一個明白的轉(zhuǎn)型操作就沒有問題
Pb->cell_block;
//合法 因為cell_block是Bear的一個成員
但是當(dāng)我們寫
Pz->rotate();時,(rotate是虛擬函數(shù))pz的類型將在編譯使其決定一下兩點:
固定的可用接口,也就是說,pz只能夠調(diào)用ZooAnimal的Public接口
該接口的訪問級別(例如rotate()是ZooAnimal的一個public成員)
在每一個執(zhí)行點,pz所指的對象類型可以決定rotate()所調(diào)用的實體,類型信息的封裝并不是維護(hù)與pz之中,而是維護(hù)與link之中,此Link存在于對象的vptr和vptr所指的virtual table之間,在每一個virtual table中都有一個信息是type of info的信息
Bear b;
ZooAnimal za = b; //這樣會引起切割
Za.rotate(); //調(diào)用ZooAnimal::rotate()
為什么rotate()所調(diào)用的是ZooAnimal實體而不是Bear實體?為什么za的vptr不指向Bear的virtual table
編譯器在初始化以及賦值操作(將一個對象賦值給另一個對象)之間做了仲裁,編譯器必須確保如果某個對象含有一個或一個以上的vptrs,那么vptrs的內(nèi)容不會被基類對象初始化或改變
加入ZooAnimal->Bear->Panda 繼承關(guān)系
ZooAnimal za;
ZooAnimal * pza;
Bear b;
Panda* pp = new Panda;
Pza = *b
將za或b的地址,或pp所含的內(nèi)容(也是個地址)指定給pza,顯然不是問題,一個指針或一個引用值所以支持多態(tài),是因為它們并不引發(fā)內(nèi)存中任何“與類型有關(guān)的內(nèi)存委托操作”,會受到改變的只是它們所指向的內(nèi)存的“大小和內(nèi)容解釋方式”而已。
所謂與類型有關(guān)的內(nèi)存委托操作是指這個類型被編譯所認(rèn)識的大小,比如上面使用pz->cell_block.
大小和內(nèi)容解釋方式是在編譯期間發(fā)生的,但是對于多態(tài)來說,是一個函數(shù),但是函數(shù)是不依附于對象的,如果只要訪問的對象中存在這個函數(shù)并且這個函數(shù)的訪問級別可以達(dá)到,編譯期間就可以實現(xiàn),但是等到運行期間,如果發(fā)現(xiàn)這個函數(shù)是一個虛函數(shù),這個時候在虛函數(shù)表中的第一個位置就是關(guān)于這個類型的所有信息,這個時候就會知道這個對象對應(yīng)的真實類型是什么。需要分清這兩點的差異