基類指針和子類指針之間相互賦值
(1)將子類指針賦值給基類指針時,不需要進行強制類型轉換,C++編譯器將自動進行類型轉換。因為子類對象也是一個基類對象。
(2)將基類指針賦值給子類指針時,需要進行強制類型轉換,C++編譯器將不自動進行類型轉換。因為基類對象不是一個子類對象。子類對象的自增部分是基類不具有的。(強制轉換告訴編譯器為對象增加子類所特有的部分)
fish* fh1; animal* an1 = new animal; fh1 = (fish*)an1;
原理:
當我們構造fish類的對象時,首先要調用animal類的構造函數去構造animal類的構造函數,然后才調用fish類的構造函數完 成自身部分的構造,從而拼接出一個完整的fish對象。
fish對象在內存中的存儲
Animal對象的內存 |
Fish繼承部分 |
當我們將fish類對象轉換為animal類對象時,該對象就被認為是原對象整個內存模型的上半部 分,也就是圖中animal對象的內存部分。當我們利用類型轉換后的對象指針去調用它的方法時,自然是調用它所在的內存中的方法。
多態
多態與非多態的實質區別就是函數地址是早綁定還是晚綁定(多態)。如果函數的調用,在編譯器編譯期間就可以確定函數的調用地址,並生產代碼,是靜態的,就是說地址是早綁定的。而如果函數調用的地址不能在編譯器期間確定,需要在運行時才確定,這就屬於晚綁定。
最常見的用法就是聲明基類的指針,利用該指針指向任意一個子類對象,調用相應的虛函數,可以根據指向的子類的不同而實現不同的方法。如果沒有使用虛函數的話,即沒有利用C++多態性,則利用基類指針調用相應的函數的時候,將總被限制在基類函數本身,而無法調用到子類中被重寫過的函數。
代碼形式 對於虛函數 對於非虛函數
作用 綁定方式 作用 綁定方式
類名::函數() 調用指定類的指定函數 靜態綁定 調用指定類的指定函數 靜態綁定
對象名.函數() 調用指定對象的指定函數 靜態綁定 調用指定對象的指定函數 靜態綁定
引用變量.函數() 調用被引用對象所屬類的指定函數 動態綁定 調用引用變量所屬類的指定函數 靜態綁定
指針->函數() 調用被引用對象所屬類的指定函數 動態綁定 調用指針變量所屬類的指定函數 靜態綁定
從上表可以看出,執行動態綁定的只有通過地址,即只有通過指針或引用變量才能實現,而且還必須是虛函數。從概念上來說,虛函數機制只有在應用於地址時才有效,因為地址在編譯階段提供的類型信息不完全。