轉自:程序員
https://blog.csdn.net/hackbuteer1/article/details/7558868面試
注:數據結構
該博主是個大牛,雖然早已經不更新了,可是分享了不少數據結構的面試題,值得翻閱學習。函數
重點筆記摘要以下:學習
下面是虛函數的一個典型應用。虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並非在編譯時刻被肯定的,而是在運行時刻被肯定的。因爲編寫代碼的時候並不能肯定被調用的是基類的函數仍是哪一個派生類的函數,因此被成爲「虛」函數。請看例子:this
class A { public: virtual void foo() { cout<<"A::foo() is called"<<endl; } }; class B : public A { public: void foo() { cout<<"B::foo() is called"<<endl; } }; int main(void) { A *a = new B(); a->foo(); // 在這裏,a雖然是指向A的指針,可是被調用的函數(foo)倒是B的! return 0; }
虛函數只能藉助於指針或者引用來達到多態的效果。spa
關於純虛函數:.net
定義:設計
純虛函數是在基類中聲明的虛函數,它在基類中沒有定義,但要求任何派生類都要定義本身的實現方法。在基類中實現純虛函數的方法是在函數原型後加「=0」。如: virtual void funtion1()=0指針
爲何要有純虛函數?
由於有兩個問題:
一、爲了方便使用C++的多態特性,咱們經常須要在基類中定義虛函數。
二、在不少狀況下,基類自己生成對象是不合情理的。例如,動物做爲一個基類能夠派生出老虎、孔雀等子類,但動物自己生成對象明顯不合常理。
爲了解決上述問題,引入了純虛函數的概念。將函數定義爲純虛函數(方法:virtual ReturnType Function()= 0;),則編譯器要求在派生類中必須予以重寫以實現多態性。同時含有純虛擬函數的類稱爲抽象類,它不能生成對象。這樣就很好地解決了上述兩個問題。(說的很是不錯)
再次「囉嗦」1:聲明瞭純虛函數的類是一個抽象類。因此,用戶不能建立類的實例,只能建立它的派生類的實例。派生類僅僅只是繼承函數的接口。
再次「囉嗦」2:純虛函數的意義,讓全部的類對象(派生類對象)均可以執行純虛函數的動做,但類沒法爲純虛函數提供一個合理的缺省實現(無默認實現)。因此基類純虛函數的聲明就是在告訴子類的設計者,「你必須提供一個純虛函數的實現,但我不知道你會怎樣實現它」。
再次「囉嗦」3:避免了像「動物」這樣的基類能夠實例化,即不能生成對象。
總結:純虛函數用來規範派生類的行爲,即接口
理解了純虛函數,沒想到還能稍帶把抽象類也學習了!
抽象類:
定義:稱帶有純虛函數的類爲抽象類
注意:
1. 抽象類只能做爲基類來使用,其純虛函數的實現由派生類給出。若是派生類中沒有從新定義純虛函數,而只是繼承基類的純虛函數,則這個派生類仍然仍是一個抽象類。若是派生類中給出了基類純虛函數的實現,則該派生類就再也不是抽象類了,它是一個能夠創建對象的具體的類。
2. 抽象類是不能定義對象的。
高級總結(仍是有不少不懂的地方):
總結:一、純虛函數聲明以下: virtual void funtion1()=0; 純虛函數必定沒有定義,純虛函數用來規範派生類的行爲,即接口。包含純虛函數的類是抽象類,抽象類不能定義實例,但能夠聲明指向實現該抽象類的具體類的指針或引用。二、虛函數聲明以下:virtual ReturnType FunctionName(Parameter);虛函數必須實現,若是不實現,編譯器將報錯,錯誤提示爲:error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"三、對於虛函數來講,父類和子類都有各自的版本。由多態方式調用的時候動態綁定。四、實現了純虛函數的子類,該純虛函數在子類中就變成了虛函數,子類的子類即孫子類能夠覆蓋該虛函數,由多態方式調用的時候動態綁定。五、虛函數是C++中用於實現多態(polymorphism)的機制。核心理念就是經過基類訪問派生類定義的函數。六、在有動態分配堆上內存的時候,析構函數必須是虛函數,但沒有必要是純虛的。七、友元不是成員函數,只有成員函數才能夠是虛擬的,所以友元不能是虛擬函數。但能夠經過讓友元函數調用虛擬成員函數來解決友元的虛擬問題。八、析構函數應當是虛函數,將調用相應對象類型的析構函數,所以,若是指針指向的是子類對象,將調用子類的析構函數,而後自動調用基類的析構函數。