成員函式一般化三個結論
#include
using std::cout;
using std::endl;
class employee
};class dev : public employee
};int main()
1. 如果以「基類指標」指向「派生類物件」,那麼經由該指標只能呼叫基類所定義的函式
2. 如果以「派生類指標」指向「基類物件」,必須先做明顯的轉換操作。這種做法很危險,
不符合真實生活經驗,在程式設計上也會帶給程式設計師困惑
3. 如果基類和派生類都定義了「相同名稱的成員函式」,那麼經由物件指標呼叫成員函式時,
到底呼叫哪乙個函式,必須視該指標的原始型別而定,而不是視指標所指的物件的型別而定
基類的指標指向派生類的物件
#include
using namespace std;
class a
virtual ~a()
};class b: public a
~b()
};int main()
output:ab
0xc1e010 0xc1e010
~b~a
由於類a的析構函式是虛函式,所以其物件的儲存空間中包含了虛表;
類b繼承了類a,所以類b的析構函式也變成了虛析構函式,類b物件的
儲存空間中也包含了虛表;根據多型的原則,用基類的指標刪除派生類物件,
實際上是通過虛指標(vptr)找到虛表(vtable),然後在找到虛函式的位址。
成員函式的虛擬化
虛函式是為了對「如果以基類指標指向派生類物件,那麼通過該指標就只能呼叫基類所定義的成員函式」
這條規則反其道而行的設計。多型就是以單一指令呼叫不同函式。
為了達到動態繫結的目的,c++編譯器通過某個**,在執行期「間接」呼叫實際上欲繫結的函式。
這樣的**稱為虛函式表(vtable)。每乙個「內含虛函式的類」,編譯器都會為它做出乙個虛函式表,
表中的每乙個元素都指向乙個虛函式的位址。此外,編譯器當然也會為類加上一項成員變數,
是乙個指向該虛函式表的指標(vptr)。
object slicing 與虛函式
對於test 4的輸出結果
由於向上強制轉型, (senior)prin, 將會造成物件的內容被切割(object slicing),當呼叫
((senior)prin).show(); prin已經是乙個被切割得只剩下半條命的物件,
由於((senior)prin).show()是傳值而非傳址操作,編譯器以所謂的拷貝建構函式把senior物件的內容複製了乙份,
使得prin的vtable內容與senior物件的vtable相同。
基類指標指向派生類物件
父類子類指標函式呼叫注意事項 1,如果以乙個基礎類指標指向乙個衍生類物件 派生類物件 那麼經由該指標只能訪問基礎類定義的函式 靜態聯翩 2,如果以乙個衍生類指標指向乙個基礎類物件,必須先做強制轉型動作 explicit cast 這種做法很危險,也不符合生活習慣,在程式設計上也會給程式設計師帶來困擾...
基類指標指向派生類物件
派生類物件也 是 基類物件,但兩者不同。派生類物件可以當做基類物件,這是因為派生類包含基類的所有成員。但是基類物件無法被當做成派生類物件,因為派生類可能具有只有派生類才有的成員。所以,將派生類指標指向基類物件的時候要進行顯示的強制轉換,否則會使基類物件中的派生類成員成為未定義的。總結 基類指標和派生...
基類指標指向派生類物件
派生類物件也 是 基類物件,但兩者不同。派生類物件可以當做基類物件,這是因為派生類包含基類的所有成員。但是基類物件無法被當做成派生類物件,因為派生類可能具有只有派生類才有的成員。所以,將派生類指標指向基類物件的時候要進行顯示的強制轉換,否則會使基類物件中的派生類成員成為未定義的。總結 基類指標和派生...