重拾C++之虛函數和虛基類以及抽象類

1、引言

    很久沒接觸過C++了,今天忽然要用一點感受號蛋疼,用慣了python感受C++一點都不會了。java

聲明瞭一個類的對象竟然用這種方法,腦子絕對是被驢(python)踢了
class A{
 ...
 }
 a=A();//尼瑪這都能行,被踢大了
2、虛函數和通常函數

    虛函數就是加了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

3、虛函數和純虛函數

    學過java的都知道有類和接口兩種不同的東西(其實我在裝逼,java也就會i++了.*_*!!),純虛函數就相似於接口,純虛函數不能在定義類中實現,但應該在可以實例化的子類中實現。定義了純虛函數的類就要抽象類(記住是抽象類不是虛基類,網上有個逼說是虛基類,此貼竟然還有好多人轉發,真是貽害不淺。好吧也許真是虛基類,那就當我是逼吧^_^)。抽象類不可以被實例化。
指針

4、虛繼承和虛基類

    虛繼承的主要是爲了解決多重繼承中出現的二義性問題,普通繼承若是一個基類經過幾條路徑繼承到了一個派生類中,那麼這個派生類將有兩個基類的副本,對這些成員的訪問將會出現二義性錯誤。
code

//虛繼承是這樣的
class A :public vritual B{
....
}

    虛基類:虛基類是指虛繼承中的基類,記住不是含有純虛函數的類(抽象類)
對象

    注意:對於虛基類的初始化即便是是間接繼承,在派生類的構造函數中也應該顯示的調用其構造函數,不然將調用默認的構造函數(沒有參數,若是沒有定義本身的構造函數,系統將會定義默認的構造函數,不然沒有默認構造函數),若是沒有默認構造函數,程序將會出錯。繼承

5、總結

    虛函數是爲了實現多態性,虛基類是爲了解決多重繼承的二義性問題,除此以外彷佛沒有任何關係(惟一有關係也是虛的,因此有關係是假的)。

    虛基類是虛繼承中的基類,抽象類是含有純虛函數的類,二者徹底不一樣。

相關文章
相關標籤/搜索