C 靜態繫結和動態繫結

2021-06-06 01:26:20 字數 2061 閱讀 8932

c++為了支援多型性,才用了動態繫結和靜態繫結。

首先理解四個名詞:

1.物件的靜態型別:物件在宣告時採用的型別,是在編譯期確定的。

2.物件的動態型別:目前所指物件的型別,是在執行期決定的。

class b

{};class c:public b

{};class d:public b

{};d* pd=new d();//pd的靜態型別是d*,動態型別也是d*

b* pb=pd; //pb的靜態型別是b*,動態型別是d*

c* pc=new c();

pb=pc; //pb的動態型別改變了,現在變成了c* ,所以從這可看出,動態型別是可以改變的,靜態型別是不可以改變的(廢話,宣告時候所表示的還能改變嗎?)

3.靜態繫結:繫結的是物件的靜態型別,某特性(比如函式)依賴於物件的靜態型別,發生在編譯期。

4.動態繫結:繫結的是物件的動態型別,某特性(比如函式)依賴於物件的動態型別,發生在執行期。

class b

;class c:public b

;class d:public b

;d* pd=new d();

b* pb=pd;

這邊我們看一下,pd->dosomething()和pb->dosomething()呼叫的是同乙個函式嗎?這邊顯然指的不是同乙個物件,因為dosomething是乙個no-virtual函式,它是金泰繫結的,也就是編譯器會在編譯期根據物件的靜態型別來選擇函式。所以pd->dosomething()就等同於d::dosomething,pb->dosomething()就等同於b::dosomething()。

再看下pd->vfun()和pb->vfun()呼叫的是同乙個函式嗎?這邊就是了,因為vfun是乙個virtual函式,它是動態繫結的,也就是說它繫結的是物件的動態型別,pb和pd雖然靜態型別不同,但是當它們指向同乙個物件的時候,他們的動態型別是相同的,都是d*,所以兩者指向的都是同乙個函式:d::vfun()。

以上介紹的是指標,對於引用(reference)的情況同樣適用。

下面我們再介紹一種特殊情況:

virtual函式是動態繫結的,而預設引數卻是靜態繫結的。

class shape;

virtual void draw(shapecolor color=red) const=0;

};class rectangle:public shape;

class circle:public shape;

//不管ps,pc,pr指向哪兒,靜態型別都是shape*

shape *ps;

shape *pc=new circle();

shape *pr=new rectangle();

ps=pr;

ps=pc;

pc->draw(shape::red); //呼叫circle::draw

pr->draw(shape::red); //呼叫rectangle::draw

pr->draw(); //呼叫rectangle::draw,使用shape::draw裡面的引數值

帶有引數的是動態繫結,預設引數的是靜態繫結。意思是你可能在呼叫「乙個定義於derived class內的virtual函式」的同時,卻使用base class為他所指定的預設引數值:

pr的動態型別是rectangle*,所以呼叫的是rectangle的virtual函式,rectangle::draw函式的預設引數應該是green,但是pr的靜態型別是shape*,所以呼叫預設引數值來自shape class而非來自rectangle class。

為什麼c++堅持這種方式來運作呢?答案在於長期效率。如果預設引數是動態繫結的,編譯器就必須有某種辦法在執行為virtual函式決定適當的引數預設值。這個比較複雜,為了程式執行的速度和編譯速度,這樣取捨,保證效率。

本篇文章參考文獻:

深入理解c++的動態繫結和靜態繫結

effective c++ 條款 37:絕不重新定義繼承而來的預設引數值

靜態繫結和動態繫結

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

靜態繫結和動態繫結

物件的靜態型別 物件在宣告是採用的型別,在編譯期確定 物件的動態型別 當前物件所指的型別,在執行期決定,物件的動態型別可以更改,但靜態型別無法更改。靜態繫結 繫結的是物件的靜態型別,某特性 比如函式 依賴於物件的靜態型別,發生在編譯期。動態繫結 繫結的是物件的動態型別,某特性 比如函式 依賴於物件的...

C 靜態和動態繫結

class a class b public a class c public a 下面逐步分析測試 及結果,c pc new c pc的靜態型別是它宣告的型別c 動態型別也是c b pb new b pb的靜態型別和動態型別也都是b a pa pc pa的靜態型別是它宣告的型別a 動態型別是pa所...