C++ — 靜態繫結與動態繫結
靜態繫結與動態繫結
——————————————————————————————————
靜態繫結,動態繫結算是一個比較偏的知識點,這個也是我在Effective C++這本書當中學習到的. 我覺得很有必要寫一篇部落格記錄.
首先我們要知道靜態型別和動態型別的概念:
靜態型別:就是它在程式中被宣告時所採用的型別(或理解為型別指標或引用的字面型別),在編譯期確定;
動態型別:目前所指物件的型別。是在執行期決定的。物件的動態型別可以更改,但是靜態型別無法更改。
接下來我引用Effective C++這本書中的例子,幫助理解:
class Shape
{
public:
enum shapeColor{Red,Green,Blue};
//所有形狀都必須提供一個函式,同來繪出自己.
virtual void draw(shapeColor color = Red) const = 0;
...
};
class Rectangle : public Shape
{
public:
//注意,賦予不同的預設引數值,這真糟糕
virtual void draw(shapeColor color = Green) const;
};
class Circle : public Shape
{
public:
virtual void draw(shapeColor color) const;
//請注意,以上這麼寫則當客戶以物件呼叫此函式,一定要指定引數值.
//因為靜態繫結下這個函式並不從其base繼承預設引數值
//但若以指標(或reference)呼叫此函式,可以不指定引數值
//因為動態繫結下這個函式會從其base繼承預設引數值
......
};
Shape *ps; // ps的靜態型別為Shape*,它沒有動態型別,因為它尚未指向任何物件;
Shape *pc = new Circle; // pc的靜態型別為Shape*,它的動態型別為Circle*;
Shape *pr = new Rectangle; // pr的靜態型別為Shape*,它的動態型別為Rectangle*;
// 動態型別可以在程式執行過程中改變(通常是經由賦值動作):
ps = pc; // ps的動態型別如今是Circle*;
ps = pr; // ps的動態型別如今是Rectangle*;
現在我們來理解何為靜態繫結和動態繫結???
靜態繫結:又名前期繫結(eraly binding),繫結的是靜態型別,所對應的函式或屬性依賴於物件的靜態型別,發生在編譯期;
動態繫結:又名後期繫結(late binding),繫結的是動態型別,所對應的函式或屬性依賴於物件的動態型別,發生在執行期;
比如常見的,virtual函式是動態繫結,non-virtual函式是靜態繫結,預設引數值也是靜態繫結.Virtual函式系動態繫結而來,
意思是呼叫了一個virtual函式時,究竟呼叫那一份函式實現程式碼,取決於付出呼叫的那個物件的動態型別:
pc->draw(shape::Red); //呼叫Circle::draw(shape::Red)
pr->draw(shape::Red); //呼叫Rectangle::draw(shape::Red)
其實這些都是老掉牙的知識點,但是今天我們帶來了virtual函式不同的地方,預設值! virtual函式是動態繫結的,而預設引數
值為靜態繫結. 意思是你可能會在"呼叫一個定義與derived class內的virtual函式"的同時,卻使用base class為他所指定的預設
參數值.
pr->draw(); //呼叫Rectangle::draw(shape::Red)!
此例當中,pr的動態型別為Rectangle*,所以呼叫的是Rectangle的virtual函式,一如你所預料.Rectangle::draw函式的預設值應
該是Green,但由於pr的靜態型別為shape*,所以此一呼叫的預設引數值來自shape class而非Rectangle class!結局是這個函式調
用有這奇怪並且幾乎沒有人預料得到的組合,由shape class和Rectangle class的draw生命式各處一份力.以上事實不只侷限於
"ps,pc和pr都是指標"的情況;即使把指標換成references問題依然存在.重點在於draw是一個virtual函式,而它有個預設引數值在
derived class中被重新定義了.
為什麼C++堅持以這種乖張的方式來運作呢? 答案在於執行期效率. 如果預設引數值為動態繫結,編譯器就必須有某種方法在執行
期為virtual函式決定適當的引數預設值.這比目前實行的"在編譯器決定"的機制更慢而且更復雜.為了程式的執行速度和編譯器實
現上的簡易度,C++做了這樣的取捨,其結果就是你如今所享受的執行效率. 但是如果你重新定義了繼承而來的預設引數值,而且偏
偏在預設引數值上面出現bug,那麼你可能需要一個通宵都不一定調的出來.
相關文章
- 理解靜態繫結與動態繫結
- C++的動態繫結和靜態繫結C++
- java中的靜態繫結與動態繫結Java
- 深入理解 C++ 的動態繫結和靜態繫結C++
- java繼承-靜態繫結和動態繫結Java繼承
- 動態繫結和靜態繫結的簡單理解
- php 後期靜態繫結PHP
- 動態繫結一
- 繫結變數在靜態sql和動態sql中變數SQL
- Jni函式的靜態繫結函式
- 介面(抽象類)與後期靜態繫結學習抽象
- JAVA動態繫結淺析Java
- 三、動態繫結屬性
- 動態繫結的心得 (轉)
- 對 PHP 後期靜態繫結的理解PHP
- vue 動態繫結 v-modelVue
- 動態繫結 input v-model
- Vue 動態繫結CSS樣式VueCSS
- 關於動態字串的繫結字串
- 後期靜態繫結在PHP中的使用PHP
- PHP延遲靜態繫結:static關鍵字PHP
- Laravel 中的一個後期靜態繫結Laravel
- PHP學習筆記——延遲靜態繫結PHP筆記
- 14 #### 方法分類與使用場景(繫結、靜態、類方法)
- class 和 style 資料動態繫結
- Vue select 繫結動態變數Vue變數
- 域名繫結動態IP實戰案例
- vue動態(type可變)input繫結Vue
- 介面的繫結方案和動態SQLSQL
- Vue 動態資料繫結核心方法Vue
- SQL Server動態SQL,繫結變數SQLServer變數
- java基礎:多型(動態繫結)Java多型
- 動態連結庫與靜態連結庫
- jQuery實現DOM元素事件動態繫結jQuery事件
- Java 動態繫結機制的內幕Java
- 動態生成的html元素繫結click事件HTML事件
- jquery 為動態新增的元素繫結事件jQuery事件
- java之多型(Polymorphic)、動態繫結(Dynamic Binding)、遲繫結(Late Binding)Java多型