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

2021-07-30 10:50:37 字數 2550 閱讀 3822

c++在物件導向程式設計中,存在著靜態繫結和動態繫結的定義,本節即是主要講述這兩點區分。

我是在乙個類的繼承體系中分析的,因此下面所說的物件一般就是指乙個類的例項。

首先我們需要明確幾個名詞定義:

從上面的定義也可以看出,非虛函式一般都是靜態繫結,而虛函式都是動態繫結(如此才可實現多型性)。

先看**和執行結果:

1

classa2

5};6class b : publica7

10};

11class c : publica12

15};

下面逐步分析測試**及結果,

1 c* pc = new c(); //

pc的靜態型別是它宣告的型別c*,動態型別也是c*;

2 b* pb = new b(); //

pb的靜態型別和動態型別也都是b*;

3 a* pa = pc; //

pa的靜態型別是它宣告的型別a*,動態型別是pa所指向的物件pc的型別c*;

4 pa = pb; //

pa的動態型別可以更改,現在它的動態型別是b*,但其靜態型別仍是宣告時候的a*;

5 c *pnull = null; //

pnull的靜態型別是它宣告的型別c*,沒有動態型別,因為它指向了null;

如果明白上面**的意思,請繼續,

1 pa->func();      //

a::func() pa的靜態型別永遠都是a*,不管其指向的是哪個子類,都是直接呼叫a::func();

2 pc->func(); //

c::func() pc的動、靜態型別都是c*,因此呼叫c::func();

3 pnull->func(); //

c::func() 不用奇怪為什麼空指標也可以呼叫函式,因為這在編譯期就確定了,和指標空不空沒關係;

如果注釋掉類c中的func函式定義,其他不變,即

1

class c : publica2

;45 pa->func(); //

a::func() 理由同上;

6 pc->func(); //

a::func() pc在類c中找不到func的定義,因此到其基類中尋找;

7 pnull->func(); //

a::func() 原因也解釋過了;

如果為a中的void func()函式新增virtual特性,其他不變,即

1

classa2

5};67 pa->func(); //

b::func() 因為有了virtual虛函式特性,pa的動態型別指向b*,因此先在b中查詢,找到後直接呼叫;

8 pc->func(); //

c::func() pc的動、靜態型別都是c*,因此也是先在c中查詢;

9 pnull->func(); //

空指標異常,因為是func是virtual函式,因此對func的呼叫只能等到執行期才能確定,然後才發現pnull是空指標;

分析:在上面的例子中,

1. 如果基類a中的func不是virtual函式,那麼不論pa、pb、pc指向哪個子類物件,對func的呼叫都是在定義pa、pb、pc時的靜態型別決定,早已在編譯期確定了。

同樣的空指標也能夠直接呼叫no-virtual函式而不報錯(這也說明一定要做空指標檢查啊!),因此靜態繫結不能實現多型;

2. 如果func是虛函式,那所有的呼叫都要等到執行時根據其指向物件的型別才能確定,比起靜態繫結自然是要有效能損失的,但是卻能實現多型特性;

本文**裡都是針對指標的情況來分析的,但是對於引用的情況同樣適用。

至此總結一下靜態繫結和動態繫結的區別:

1. 靜態繫結發生在編譯期,動態繫結發生在執行期;

2. 物件的動態型別可以更改,但是靜態型別無法更改;

3. 要想實現動態,必須使用動態繫結;

4. 在繼承體系中只有虛函式使用的是動態繫結,其他的全部是靜態繫結;

建議:絕對不要重新定義繼承而來的非虛(non-virtual)函式(《effective c++ 第三版》條款36),因為這樣導致函式呼叫由物件宣告時的靜態型別確定了,而和物件本身脫離了關係,沒有多型,也這將給程式留下不可預知的隱患和莫名其妙的bug;

另外,在動態繫結也即在virtual函式中,要注意預設引數的使用。當預設引數和virtual函式一起使用的時候一定要謹慎,不然出了問題怕是很難排查。

看下面的**:

1

classe2

8};9class f : publice10

16};

1718

void

test2()

19

為什麼會有這種情況,請看《effective c++ 第三版》 條款37。

這裡只給出建議:

絕對不要重新定義乙個繼承而來的virtual函式的預設引數值,因為預設引數值都是靜態繫結(為了執行效率),而virtual函式卻是動態繫結。

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

感謝原作者分享 c 在物件導向程式設計中,存在著靜態繫結和動態繫結的定義,本節即是主要講述這兩點區分。我是在乙個類的繼承體系中分析的,因此下面所說的物件一般就是指乙個類的例項。首先我們需要明確幾個名詞定義 從上面的定義也可以看出,非虛函式一般都是靜態繫結,而虛函式都是動態繫結 如此才可實現多型性 先...

C 靜態繫結和動態繫結

c 為了支援多型性,才用了動態繫結和靜態繫結。首先理解四個名詞 1.物件的靜態型別 物件在宣告時採用的型別,是在編譯期確定的。2.物件的動態型別 目前所指物件的型別,是在執行期決定的。class b class c public b class d public b d pd new d pd的靜態...

靜態繫結和動態繫結

c 中,非虛函式都是靜態繫結,而虛函式卻是動態繫結。為了能夠更清楚地了解靜態繫結與動態繫結,我們可以看下面這個例子 include using namespace std class b 那麼兩次呼叫fun 函式是否相同呢?當然,如果d中沒有定義fun 函式 如例子中 那麼兩次呼叫的行為肯定會是一樣...