C 中動態繫結和靜態繫結

2021-04-26 01:46:10 字數 1225 閱讀 7153

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 中動態繫結和靜態繫結

2009 03 27 15 35 1053人閱讀收藏 舉報c funclass 編譯器c c 中,非虛函式都是靜態繫結,而虛函式卻是動態繫結。為了能夠更清楚地了解靜態繫結與動態繫結,我們可以看下面這個例子 include using namespace std class b 那麼兩次呼叫fun 函...

C 動態繫結和靜態繫結

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

c 動態繫結和靜態繫結

為了支援c 的多型性,才用了動態繫結和靜態繫結。1 物件的靜態型別 物件在宣告時採用的型別。是在編譯期確定的。2 物件的動態型別 目前所指物件的宣告。在執行期決定。物件的動態型別可以更改,但是靜態型別無法更改。關於物件的靜態型別和動態型別,看乙個示例 class a class b public a...