記得當初阿里面試的時候被問道這個問題,平時自己面對這個方法都習以為常的使用,c++多型和動態繫結不就是這麼實現的嘛,但是還真沒有刻意去關注其中的原理。今天特意看了相關資料,現在分享給大家。
其實這塊我們需要分為兩種情況來考慮,第一種是類繼承(靜態繫結),第二種是父類中包含虛函式(動態繫結)。
2.1 沒有虛函式的繼承
如果以乙個基礎類指標指向乙個派生類物件,那麼經由該指標只能訪問基礎類定義的函式(靜態繫結)。
如果以乙個派生類類指標指向乙個基礎類物件,必須先做強制轉型動作(explicit cast),這種做法很危險,也不符合生活習慣,在程式設計上也會給程式設計師帶來困擾。(一般不會這麼去使用)
如果基礎類和派生類類定義了相同名稱的成員函式
,那麼通過物件指標呼叫成員函式時,到底呼叫那個函式要根據指標的原型來確定
,而不是根據指標實際指向的物件型別確定。(指標型別是誰就呼叫誰)
這塊我需要說明一下為何基礎類可以指向派生類物件,而派生類不去指向父類物件。
通常來說,子類總是含有一些父類沒有的成員變數,或者方法函式。而子類肯定含有父類所有的成員變數和方法函式。所以用父類指標指向子類時,沒有問題,因為父類有的,子類都有,不會出現非法訪問問題。
但是如果用子類指標指向父類的話,一旦訪問子類特有的方法函式或者成員變數,就會出現非法,因為被子類指標指向的由父類建立的物件,根本沒有要訪問的那些內容,那些是子類特有的,只有用子類初始化物件時才會有。
2.2 包含虛函式的繼承
有虛函式的繼承,那麼父類指標指向子類物件就是我們常見的多型實現,也就是動態繫結。
虛函式就是為了對「如果你以乙個基礎類指標指向乙個衍生類物件,那麼通過該指標,你只能訪問基礎類定義的成員函式」這條規則反其道而行之的設計。
重點:
當然這裡還包括純虛函式,只要是擁有純虛函式的類,就是抽象類,它們是不能夠被例項化的(只能被繼承)。
如果乙個繼承類沒有改寫父類中的純虛函式,那麼他也是抽象類,也不能被例項化。抽象類不能被例項化,不過我們可以擁有指向抽象類的指標,以便於操縱各個衍生類。
當定義乙個指向子類例項的父類指標的時候,記憶體中例項化了子類,由於子類繼承了父類,因此記憶體中的子類裡包含父類的所有成員。但由於申明的是父類指標,因此該指標不能夠訪問子類的成員,而只能訪問父類的成員。
然而在父類裡可以宣告純虛函式和定義虛函式,使用父類指標訪問**虛函式或純虛函式**的時候,訪問到的是子類裡重寫的函式。
當然,對於虛函式,如果子類裡沒有對其重寫的話,仍然訪問到父類裡定義的虛函式
。可見虛函式和純虛函式的卻別僅僅在於:純虛函式沒有定義,只有宣告。
區別動態繫結與靜態繫結
參考文獻:
c 父類指標指向子類物件
父類子類指標函式呼叫注意事項 1,如果以乙個基礎類指標指向乙個衍生類物件 派生類物件 那麼經由該指標只能訪問基礎類定義的函式 靜態聯翩 2,如果以乙個衍生類指標指向乙個基礎類物件,必須先做強制轉型動作 explicit cast 這種做法很危險,也不符合生活習慣,在程式設計上也會給程式設計師帶來困擾...
c 父類指標指向子類物件
父類子類指標函式呼叫注意事項 1,如果以乙個基礎類指標指向乙個衍生類物件 派生類物件 那麼經由該指標只能訪問基礎類定義的函式 靜態聯翩 2,如果以乙個衍生類指標指向乙個基礎類物件,必須先做強制轉型動作 explicit cast 這種做法很危險,也不符合生活習慣,在程式設計上也會給程式設計師帶來困擾...
父類指標指向子類物件問題
子類與父類指標呼叫相關注意事項 1,如果以乙個基礎類指標指向乙個衍生類物件 派生類物件 那麼經由該指標只能訪問基礎類定義的函式 靜態聯翩 2,如果以乙個衍生類指標指向乙個基礎類物件,必須先做強制轉型動作 explicit cast 這種做法很危險,也不符合生活習慣,在程式設計上也會給程式設計師帶來困...