虛函式總是跟多型聯絡在一起,引入虛函式可以使用基類指針對繼承類物件進行操作!
虛函式:繼承介面(函式名,引數,返回值),但是實現不繼承(函式體)
非虛函式:繼承介面,也繼承實現;
1)虛析構函式(當乙個類打算作為基類使用時候,其析構函式必須是虛函式)
建構函式可以為虛函式嗎? 不可以,在生成物件的時候,必須向編譯器明確指定要生成什麼型別的物件,因而不存在虛函式的問題;只有當物件已經存在,我用什麼介面去操作它的問題;
例子:class a
;class b: public a
;int main()
這裡通過指標a去呼叫b類的析構函式,但是如果 ~a()不是虛析構函式,就不存在多型,就會去呼叫a中的析構函式,最後結果可能是b物件中的a成分被析構了,其他還殘留;所以當乙個類作為基類時候,其析構函式必須是虛函式,這樣防止出現析構不完全的情況;
2)當虛函式出現在構造、析構函式中時(即在建構函式中呼叫虛函式),函式退化為普通函式。為什麼? <>中條款
例子:**自<>中條例9)
class transaction ;
transaction::transaction()
class buytransaction : public transaction ;
這裡呼叫buytransaction的建構函式,因為buytransaction是繼承類所以先呼叫基類的建構函式,此時派生類獨有的那部分還未初始化,<>中這麼解釋:「這個物件內的buytransaction成分還未初始化,最安全的辦法是當他不存在,物件在derived成分還未初 始化時該物件不會成為乙個derived物件」所以transaction 的建構函式會呼叫基類的 logtransaction() const;而且此處是個純虛函式,會報錯
3)虛函式與覆蓋,過載,隱藏
過載首先出現在非繼承關係當中,當同乙個類中,兩個函式的引數不同,名字相同,返回值型別無所謂(函式返回值不作為過載的參考,因為函式呼叫時候不出現返回值);
注意兩個函式可以僅僅因為const與非const的差別來實現過載;
虛函式與覆蓋均出現在乙個繼承體系中,覆蓋針對的是普通函式,當父類子類中出現同名(相同返回值,相同引數,相同函式名)要求絕對一致;
虛函式在父類子類中,首先父類中宣告該函式為virtual,那麼子類可以重新定義該函式的實現,這裡主要涉及多型,就是覆蓋的情況加上virtual,通過指標或者引用實現多型;
隱藏顯得簡單粗暴,在繼承類中只要出現於父類同名(只要求同樣的函式名/變數名,其他返回值,virtual 非virtual不管)的函式,則用物件呼叫同名函式時候,基類對應的同名函式、變數隱藏,如果要訪問其父類的同名成員應該明確使用 基類名::成員來訪問;
例子:class a
;void process(int i,char c); //過載,編譯期間即可確定該呼叫哪個函式
char process(double d,int c); //只要函式名相同,返回無所謂,引數不同
void process(int i);
void process(int i)const; // 此處相當於void process(const a *this,int i);
void process(consttint i); //這裡僅僅因為const屬性不同即可實現過載
virtual int foo(int, char);
int foo2(){};
void foo3(int,int ){};
};class b: public a
; //虛函式,這裡函式介面要嚴格一致(大部分編譯器要求返回值也要一致)
int process(); //隱藏基類函式
int foo2(){}; // 這裡不含虛屬性,會覆蓋
int foo3(); //會隱藏a類的foo3
};int main()
總結:
1)覆蓋與虛函式是一對兄弟,要求函式的返回值,函式名,引數嚴格一致,虛函式是覆蓋加上virtual的情況;
2) 隱藏是覆蓋的推廣,覆蓋是隱藏的特例,只要求函式名一樣,其他不管,在繼承體系中,子類的同名函式會將父類的同名函式隱藏;
3)當使用指標時候,指向基類的指標會根據實際物件的型別,選擇相應的虛函式執行,如果派生類沒有重新定義基類的虛函式,那麼依然執行基類的虛函式;
4)當不存在虛函式的情況下,使用基類的指標,不會下降到派生類中去搜尋函式;所以virtual屬性相當於告訴基類指標:當執行我時,請到相應物件中搜尋對應的虛函式;
5)純虛函式所在的類是抽象類,不能例項化,定義了純虛函式意味著這個函式只能為父類,其負責定義介面而不負責實現;
6)當使用物件來呼叫相應的函式時候,主要考慮的是對基類同名函式的隱藏(包括覆蓋),而不需要考慮多型;
7)注意構造析構函式中不能呼叫虛函式,當執行派生類的建構函式時候,先構造的是其基類成分,再執行派生類成分的構造,虛函式此時無意義;
8)c++是個細節非常多,非常複雜的語言;
參考:《effective c++》
C 函式 過載 覆蓋 隱藏
在c 的類中函式定義的時候會有 過載,覆蓋 也成為重寫 隱藏 也成為重定義 三種情況下面說說他們的區別,以及一些注意事項 學習c 中的類,主要有兩種,一種是用struct 關鍵字 定義的,預設情況下類中的成員是public屬性,而另一種使用class 關鍵字 定義的預設是private屬性的。子類在...
C 虛函式覆蓋 過載
cbase類處於作用域的外層,派生類的方法對於其將是不可見的,即隱藏的。而在派生類中,如果有過載函式時,基類函式將會被隱藏,否則基類函式就不被隱藏。includeusing namespace std 基類 class cbase virtual void jump void run int spe...
C 虛函式覆蓋 過載
在c 語言中,虛函式是非常重要的概念,虛函式是實現c 物件導向中多型性和繼承性的基石。而多型性和繼承性則是物件導向語言的精髓。掌握虛函式才算是真正掌握c 語言,而c 語言中虛函式的繼承覆蓋與函式過載有些類似,很多初學者搞不清他們之間的關係。首先要明確覆蓋 override 與過載 overload ...