引言一直以來都沒有寫過一篇關於概念性的文章,因為我覺得這些概念性的東西書本上都有並且說的也很詳細寫來也無用,今天突發奇想想寫
一寫,下面就和大家討論一下虛基類、虛函式與純虛函式
,一看名字就讓人很容易覺得混亂。不過不要緊待看完本文後你就會理解了。
正文虛基類
在說明其作用前先看一段**
classa
;classb:publica
從**中可以看出類
b c都繼承了類a的
ivalue成員,
因此類b c
都有乙個成員變數
ivalue
,而類d
又繼承了
b c,這樣類
d就有乙個重名的成員
ivalue(
乙個是從類
b中繼承過來的,乙個是從類
c中繼承過來的
).在主函式中呼叫
d.ivalue
因為類d
有乙個重名的成員
ivalue
編譯器不知道呼叫
從誰繼承過來的
ivalue
所以就產生的二義性的問題
.正確的做法應該是加上作用域限定符
d.b::ivalue
表示呼叫從
b類繼承過來的
ivalue
。不過類
d的例項中就有多個
ivalue
的例項,就會占用記憶體空間。所以
c++中就引用了虛基類的概念,來解決這個問題。
classa;
class
b:virtual
publica
在繼承的類的前面加上
virtual
關鍵字表示被繼承的類是乙個虛基類,它的被繼承成員在派生類中只保留乙個例項。例如
ivalue
這個成員,從類
d這個角度上來看,它是從類b與類
c繼承過來的,而類
bc又是從類
a繼承過來的,但它們只保留乙個副本。因此在主函式中呼叫
d.ivalue
時就不會產生錯誤。
虛函式還是先看**
classa;
class
b:publica
大家以為這段**的輸出結果是什麼?有的人可能會馬上回答
funprint of class a
與funprint of class b
因為第一次輸出是引用類a的實
例啊,第二次輸出是引用類
b的例項啊。那麼我告訴你這樣想就錯啦,答案是
funprint of class a
與funprint of class a
至於為什麼輸出
這樣的結果不在本文討論的範圍之內;你就記住,不管引用的例項是哪個類的當你呼叫的時候系統會呼叫左值那個物件所屬類的方法。比如說
上面的**類
a b都有乙個
funprint
函式,因為
p是乙個
a類的指標,所以不管你將
p指標指向類
a或是類
b,最終呼叫的函式都是類a的
funprint
函式。這就是靜態聯篇,編譯器在編譯的時候就已經確定好了。可是如果我想實現跟據例項的不同來動態決定呼叫哪個函式呢?這就須要用到
虛函式(也就是動態聯篇)
classa
在基類的成員函式前加
virtual
關鍵字表示這個函式是乙個虛函式,所謂虛函式就是在編譯的時候不確定要呼叫哪個函式,而是動態決定將要調
用哪個函式,要實現虛函式必須派生類的函式名與基類相同,引數名引數型別等也要與基類相同。但派生類中的
virtual
關鍵字可以省略,也表
示這是乙個虛函式。下面來解決一下**,宣告乙個基類的指標(必須是基類,反之則不行)p,把
p指向類
a的例項
a,呼叫
funprint
函式,這
時系統會判斷
p所指向的例項的型別
,如果是
a類的例項就呼叫a類的
funprint
函式,如果是
b類的例項就呼叫b類的
funprint
函式。純虛函式
與其叫純虛函式還不如叫抽象類
,它只是宣告乙個函式但不實現它,讓派生類去實現它
,其實這也很好理解。
class
vehicle
;class
camion:
public
vehicle
如上**,定義了乙個交通工具類(
vehicle
),類中有一函式可列印出交通工具的輪胎個數,但交通工具很多輪胎個數自然也就不確定,所以
就把它定義為純虛函式
,也就是光定義函式名不去實現它,類
camion
繼承了vehicle
並實現了裡面的**,列印出有
4個輪胎。
bike
類也是一樣。
有一點須要注意一下,純虛函式不能實化化,但可以宣告指標。
總結虛基類
1, 乙個類可以在乙個類族中既被用作虛基類,也被用作非虛基類。
2, 在派生類的物件中,同名的虛基類只產生乙個虛基類子物件,而某個非虛基類產生各自的子物件。
3, 虛基類子物件是由最派生類的建構函式通過呼叫虛基類的建構函式進行初始化的。
4, 最派生類是指在繼承結構中建立物件時所指定的類。
5, 派生類的建構函式的成員初始化列表中必須列出對虛基類建構函式的呼叫;如果未列出,則表示使用該虛基類的預設建構函式。
6, 從虛基類直接或間接派生的派生類中的建構函式的成員初始化列表中都要列出對虛基類建構函式的呼叫。但只有用於建立物件的最派生
類的構造函式呼叫虛基類的建構函式,而該派生類的所有基類中列出的對虛基類的建構函式的呼叫在執行中被忽略,從而保證對虛基類子物件
只初始化一次。
7, 在乙個成員初始化列表中同時出現對虛基類和非虛基類建構函式的呼叫時,虛基類的建構函式先於非虛基類的建構函式執行。
虛函式1,
虛函式是非靜態的、非內聯的成員函式,而不能是友元函式,但虛函式可以在另乙個類中被宣告為友元函式。
2, 虛函式宣告只能出現在類定義的函式原型宣告中,而不能在成員函式的函式體實現的時候宣告。
3, 乙個虛函式無論被公有繼承多少次,它仍然保持其虛函式的特性。
4,若類中乙個成員函式被說明為虛函式,則該成員函式在派生類中可能有不同的實現。當使用該成員函式操作指標或引用所標識的物件時
,對該成員函式呼叫可採用動態聯編。
5,定義了虛函式後,程式中宣告的指向基類的指標就可以指向其派生類。在執行過程中,該函式可以不斷改變它所指向的物件,呼叫不同
版本的成員函式,而且這些動作都是在執行時動態實現的。虛函式充分體現了物件導向程式設計的動態多型性。
純虛函式
版本的成員函式,而且這些動作都是在執行時動態實現的。虛函式充分體現了物件導向程式設計的動態多型性。
純虛函式
1, 當在基類中不能為虛函式給出乙個有意義的實現時,可以將其宣告為純虛函式,其實現留待派生類完成。
2, 純虛函式的作用是為派生類提供乙個一致的介面。
3, 純虛函式不能實化化,但可以宣告指標。
總結:不是虛函式,是靜態聯篇,在編譯的時候就確定好了,所以呼叫那個跟左值一致,若是虛函式,是動態聯翩,在執行時確定,呼叫跟右值型別一致的
理解虛基類 虛函式與純虛函式的概念
虛基類在說明其作用前先看一段 從 中可以看出類b c都繼承了類a的ivalue成員,因此類b c都有乙個成員變數ivalue 而類d又繼承了b c,這樣類d就有乙個重名的成員 ivalue 乙個是從類b中繼承過來的,乙個是從類c中繼承過來的 在主函式中呼叫d.ivalue 因為類d有乙個重名的成員i...
理解虛基類 虛函式與純虛函式的概念
虛基類 在說明其作用前先看一段 class a class b public a 大家以為這段 的輸出結果是什麼?有的人可能會馬上回答funprint of class a 與 funprint of class b 因為第一次輸出是引用類a的實 例啊,第二次輸出是引用類b的例項啊。那麼我告訴你這樣...
C 虛基類 虛函式與純虛函式
虛基類 在說明其作用前先看一段 classa class b publica classc publica classd public b publicc void main 從 中可以看出類b c都繼承了類a的ivalue成員,因此類b c都有乙個成員變數ivalue 而類d又繼承了b c,這樣類...