C 中的動態繫結與靜態繫結

2021-05-23 16:17:30 字數 1259 閱讀 8595

c++中,非虛函式都是靜態繫結,而虛函式卻是動態繫結

重點:建構函式和析構函式中呼叫虛函式,虛函式是靜態繫結的,本類只會呼叫類本身的虛函式。

為了能夠更清楚地了解靜態繫結與動態繫結,我們可以看下面這個例子:

#include

using namespace std;

class b

那麼兩次呼叫fun()函式是否相同呢?當然,如果d中沒有定義fun()函式(如例子中),那麼兩次呼叫的行為肯定會是一樣的,為:

我來自b

我來自b

但是呼叫過程卻不同。

pb->fun(); //pb為指向b型別的指標,直接呼叫b中的fun()函式。

pd->fun(); //pd為指向d型別的指標,編譯器首先在d中查詢fun()函式的宣告,沒有找到,然後到d的基類b中去找,找到fun(),停止查詢。

但如果d中有自己定義的fun()函式,那執行結果就會不同:

取消上面例子中的注釋,結果為:

我來自b

我來自d

過程:pb->fun(); //呼叫b::fun()

pd->fun(); //呼叫d::fun()

原因就是,(non-virtual)非虛函式都是靜態繫結,也就是說,由於pb被宣告為指向b型別的指標,那麼通過pb呼叫的(non-virtual)非虛函式永遠是b所定義的版本,即使pb指向乙個型別為「b的派生類d「的物件。

但另一方面,(virtual)虛函式卻是動態繫結,那麼不管是通過什麼型別的指標呼叫的這個虛函式,都會根據指標實際指向的物件型別來決定虛函式的呼叫,而與指標型別無關。如果fun()函式為虛函式,那麼不管是通過pb還是pd呼叫fun()函式,都會呼叫d::fun(),因為pb和pd真正指向的都是同乙個型別d的物件。請看如下**:

class b

程式中把fun函式宣告為虛函式,所以不管是通過pb還是pd呼叫fun()函式,都會呼叫d::fun(),因為pb和pd真正指向的都是同乙個型別d的物件。程式的輸出結果驗證了這一點:

我來自d

我來自d

因此在c++中,絕對不要重新定義繼承而來的(non-virtual)非虛函式,因為這樣的話,函式的呼叫決定因素不在物件本身,而與呼叫函式的指標型別有關,這將給程式留下不可預知的隱患。

如上例,任何乙個物件d都可能表現出b或d的行為,決定因素不在x物件本身,而在於指向x的指標型別。同時,絕對不要重新定義乙個繼承而來的virtual函式的預設引數值,因為預設引數值都是靜態繫結,而virtual函式卻是動態繫結。

C 動態繫結與靜態繫結

為了支援c 的多型性,才用了動態繫結和靜態繫結。理解他們的區別有助於更好的理解多型性,以及在程式設計的過程中避免犯錯誤。需要理解四個名詞 1 物件的靜態型別 物件在宣告時採用的型別。是在編譯期確定的。2 物件的動態型別 目前所指物件的型別。是在執行期決定的。物件的動態型別可以更改,但是靜態型別無法更...

C 靜態繫結與動態繫結

c 中由於繼承導致物件的指標和引用具有兩種不同的型別,靜態型別和動態型別。物件的靜態型別 物件在宣告時採用的型別,在編譯時確定 物件的動態型別 目前所指物件的型別,在執行期時確定。特別說明 靜態型別是,指標或引用宣告時的型別 動態型別是,指標或引用實際指向的型別。靜態繫結 繫結的是物件的靜態型別,函...

c 的動態繫結與靜態繫結

十分淺顯易懂。為了支援c 的多型性,才用了動態繫結和靜態繫結。理解他們的區別有助於更好的理解多型性,以及在程式設計的過程中避免犯錯誤,需要理解四個名詞 1 物件的靜態型別 物件在宣告時採用的型別。是在編譯期確定的。2 物件的動態型別 目前所指物件的型別。是在執行期決定的。物件的動態型別可以更改,但是...