很久沒接觸過C++了,今天忽然要用一點感受號蛋疼,用慣了python感受C++一點都不會了。java
聲明瞭一個類的對象竟然用這種方法,腦子絕對是被驢(python)踢了 class A{ ... } a=A();//尼瑪這都能行,被踢大了
虛函數就是加了vritual關鍵字的函數,引入虛函數的目的是爲了實現多態性(在此爲運行時的多態性),便可以經過父類的指針調用子類的對象,從而產生不一樣的效果。
python
virtual void show(){ cout<<"hello my name is a"<<endl; }
廢話很少說,爲了展現虛函數和通常函數的區別看看下面一個個例子:ios
#include<iostream> using namespace std; class A{ private: int a; int b; public: A(int a,int b){ this->a=a; this->b=b; cout<<"hello base A"<<endl; cout<<a<<'-'<<b<<endl; } //定義一個虛函數 virtual void show(){ cout<<"hello my name is a"<<endl; } }; class D:public A{ public: D(int a,int b):A(a,b){ cout<<"hello base A"<<endl; cout<<a<<'-'<<b<<endl; } void show(){ cout<<"hello my name is d"<<endl; } }; class E:public A{ public: E(int a,int b):A(a,b){ cout<<"hello base A"<<endl; cout<<a<<'-'<<b<<endl; } void show(){ cout<<"hello my name is e"<<endl; } }; int main() { A *p; D d = D(1,2); p=&d; p->show(); E e = E(1,2); p=&e; p->show(); }
編譯,運行輸出中有這麼兩行:函數
hello my name is d hello my name is e
而後去掉關鍵字vritual,在編譯運行,上面兩行變成了this
hello my name is a hello my name is a
看到區別了吧!對於普通函數,雖然父類的指針指向了子類的對象,可是調用的仍然是父類的函數,而虛函數則是執行子類中新定義的函數。
spa
學過java的都知道有類和接口兩種不同的東西(其實我在裝逼,java也就會i++了.*_*!!),純虛函數就相似於接口,純虛函數不能在定義類中實現,但應該在可以實例化的子類中實現。定義了純虛函數的類就要抽象類(記住是抽象類不是虛基類,網上有個逼說是虛基類,此貼竟然還有好多人轉發,真是貽害不淺。好吧也許真是虛基類,那就當我是逼吧^_^)。抽象類不可以被實例化。
指針
虛繼承的主要是爲了解決多重繼承中出現的二義性問題,普通繼承若是一個基類經過幾條路徑繼承到了一個派生類中,那麼這個派生類將有兩個基類的副本,對這些成員的訪問將會出現二義性錯誤。
code
//虛繼承是這樣的 class A :public vritual B{ .... }
虛基類:虛基類是指虛繼承中的基類,記住不是含有純虛函數的類(抽象類)
對象
注意:對於虛基類的初始化即便是是間接繼承,在派生類的構造函數中也應該顯示的調用其構造函數,不然將調用默認的構造函數(沒有參數,若是沒有定義本身的構造函數,系統將會定義默認的構造函數,不然沒有默認構造函數),若是沒有默認構造函數,程序將會出錯。繼承
虛函數是爲了實現多態性,虛基類是爲了解決多重繼承的二義性問題,除此以外彷佛沒有任何關係(惟一有關係也是虛的,因此有關係是假的)。
虛基類是虛繼承中的基類,抽象類是含有純虛函數的類,二者徹底不一樣。