加入自己一些理解....
在c++
中,聯編是指乙個電腦程式的不同部分彼此關聯的過程。按照聯編所進行的階段不同,可分為兩種不同的聯編方法:靜態聯編和動態聯編。
1.
靜態聯編
靜態聯編是指聯編工作在編譯階段完成的,這種聯編過程是在程式執行之前完成的,又稱為早期聯編。要實現靜態聯編,在編譯階段就必須確定程式中的操作呼叫(如函式呼叫)與執行該操作**間的關係,確定這種關係稱為束定,在編譯時的束定稱為靜態束定。靜態聯編對函式的選擇是基於指向物件的指標或者引用的型別。其優點是效率高,但靈活性差。 例
1:靜態聯編
#include"iostream.h"
class a
};classb:publica
該程式的執行結果為:
a a從例1
程式的執行結果可以看出,通過物件指標進行的普通成員函式的呼叫,僅僅與指標的型別有關,而與此刻指標正指向什麼物件無關。要想實現當指標指向不同物件時執行不同的操作,就必須將基類中相應的成員函式定義為虛函式,進行動態聯編。
2.動態聯編
動態聯編是指聯編在程式執行時動態地進行,根據當時的情況來確定呼叫哪個同名函式,實際上是在執行時虛函式的實現。這種聯編又稱為晚期聯編,或動態束定。動態聯編對成員函式的選擇是基於物件的型別,針對不同的物件型別將做出不同的編譯結果。
c++中一般情況下的聯編是靜態聯編,但是當涉及到多型性和虛函式時應該使用動態聯編。動態聯編的優點是靈活性強,但效率低。
動態聯編規定,只能通過指向基類的指標或基類物件的引用來呼叫虛函式,其格式為:指向基類的指標變數名
->
虛函式名(實參表)或基類物件的引用名
.虛函式名(實參表)
實現動態聯編需要同時滿足以下三個條件:
①必須把動態聯編的行為定義為類的虛函式。
②類之間應滿足子型別關係,通常表現為乙個類從另乙個類公有派生而來。
③必須先使用基類指標指向子型別的物件,然後直接或者間接使用基類指標呼叫虛函式。例2
:動態聯編
#include"iostream.h"
classa
};classb:publica
該程式的執行結果為:
a b從例2
程式的執行結果可以看出,將基類
a中的函式
f定義為虛函式後,當指標指向不同物件時執行了不同的操作,實現了動態聯編。
3.
動態聯編分析
動態聯編要求派生類中的虛函式與基類中對應的虛函式具有相同的名稱、相同的引數個數和相同的對應引數型別、返回值或者相同,或者都返回指標或引用,並且派生類虛函式所返回的指標或引用的基型別是基類中虛函式所返回的指標或引用的基型別的子型別。如果不滿足這些條件,派生類中的虛函式將丟失其虛特性,在呼叫時進行靜態聯編。例3
:通過指向基類的指標來呼叫虛函式
#include"iostream.h"
class base
結果:deriver fun1
base fun2
deriver fun3
base fun4
base fun5
為什麼這樣呢?我們可以檢視一下上兩個類的虛函式表, vs2010提供了方便的工具
執行命令:
cl /d1reportsingleclasslayout***
檔名 (***
表示類名)
圖中紅色框框的就是 類中的虛擬表,base 類的fun1, fun2, fun3用virtual宣告,所以該類虛擬表有三個指標位址
再看看drived類的。。
用了 virtual 宣告 , 所以呼叫 子類 d->fun1() 時,呼叫的是 d 的
base fun2
雖用了 virtual 宣告, 但 子類 的 fun2(int x) 有引數 與base 的不同,所以d -> fun2() 呼叫的是 b 的
base fun3
用了 virtual 宣告,也是呼叫的 d 的, 子類 d 的 fun3() 沒用virtual宣告, 但由於繼承base fun3()且同名,其也 具有 virtual 特性,可以不明寫 virtual, 但一般為了程式明了,還是加上較好,增強閱讀性。 我們驗證一下,現在增 加乙個類
inherit
繼承於 derived
class inherit:public derived
void fun4()
};
再看看其虛擬表
類的 fun3, fun4 都沒有用 virtual宣告, 但這兩都是虛函式。。執行
base *b = newinherit();//derived();
b->fun1();
b->fun2();
b->fun3();
b->fun4();
b->fun5();
呼叫結果
derived fun1
base fun2
inherit fun3
的老爸derived沒有明寫virtual,但derived的老爸base的fun3是virtual,那麼特性將不會因繼承消失
base fun4
從derived繼承virtual,但這裡用的是base的指標,base fun4沒有virtual特性,所以就這樣
base fun5
那麼用drived的指標呼叫inherit 看看
derived *d = newinherit();//derived();
d->fun1();
d->fun2(2);
d->fun3();
d->fun4();
d->fun5();
結果:derived fun1
derived fun2
inherit fun3
inherit fun4
看。。。
deriverd fun5
另,參考資料
c 動態聯編與靜態聯編
摘要 本文闡述了靜態聯編和動態聯編的概念和區別,通過具體例項分析了實現動態聯編的條件,指出了虛函式是實現動態聯編的基礎。在c 中,聯編是指乙個電腦程式的不同部分彼此關聯的過程。按照聯編所進行的階段不同,可分為兩種不同的聯編方法 靜態聯編和動態聯編。1.靜態聯編 靜態聯編是指聯編工作在編譯階段完成的,...
C 靜態聯編與動態聯編
目錄 基本概念 舉個栗子 聯編 就是將模組或者函式合併在一起生成可執行 的處理過程 函式呼叫 按照聯編所進行的階段不同,可分為兩種不同的聯編方式 靜態聯編和動態聯編。函式呼叫和實現的過程 c 只有用到多型才會用到動態連編 程式設計師是看不出來的,只是系統內部的處理 程式在編譯的時候,就知道某個類呼叫...
C 動態聯編與靜態聯編
在c 中,聯編是指乙個電腦程式的不同部分彼此關聯的過程。按照聯編所進行的階段不同,可分為兩種不同的聯編方法 靜態聯編和動態聯編。1.靜態聯編 靜態聯編是指聯編工作在編譯階段完成的,這種聯編過程是在程式執行之前完成的,又稱為早期聯編。要實現靜態聯編,在編譯階段就必須確定程式中的操作呼叫 如函式呼叫 與...