靜態繫結和動態繫結

2021-05-23 13:45:03 字數 1245 閱讀 5539

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.物件的動態型別 目前所指物件的型別,是在執行期決定的。class b class c public b class d public b d pd new d pd的靜態...

動態繫結和靜態繫結

繫結 binding 是指將變數和函式名轉換成位址的過程 絕大部分的順序執行邏輯中函式呼叫或某個確定資料型別的class型別的物件對成員呼叫都屬於靜態繫結 include using namespace std class employee class teamper public employee...