C++虛擬函式學習總結

SunshineBoyLuXing 發表於 2020-10-17
C++

一、虛擬函式學習

1.什麼是虛擬函式?

本質不是過載而是覆蓋。

2.虛擬函式有什麼作用?

實現多型。同一個宣告的不同實現。

3.子類重寫父類的普通函式和子類重寫父類的虛擬函式有什麼區別?

可以讓成員函式的操作一般化,用基類的指標指向不同的派生類物件時,基類指標呼叫其虛擬函式成員函式,則會呼叫其真正指向物件的成員函式,而不是基類中定義的成員函式(只要派生類改寫了該成員函式)

若不是虛擬函式,則不管基類指標指向的哪個派生類的物件,呼叫時都會呼叫基類中定義的哪個函式。

個人理解:就像論文初稿(基類),一稿、二稿、三稿(三個派生類),如果初稿沒有定義為虛擬函式那麼訪問一稿二稿三稿的時候只能看到初稿,但是如果定義為虛擬函式,只要派生類重寫了虛擬函式,就想看哪個稿子都可以。

4.應用場景

4.1 開發中會使用框架,開發人員無法對框架中的函式進行修改。對基類中的函式進重寫之後有的函式是用框架呼叫的。不使用虛擬函式則只能使用原框架中的函式,使用虛擬函式後則實現多型,能自己定義符合自己使用場景的函式。

4.2

二、其他問題總結

1.純虛擬函式。

基類中只宣告虛擬函式但是不實現,要求在子類中必須實現。

定義方法:virtual Functiontype FunctionName()=0;

和虛擬函式的區別是虛擬函式在基類中實現了的,子類進行覆蓋。

2.C++的多型性

編譯時多型性:通過過載函式實現
執行時多型性:通過虛擬函式實現

要實現多型需要:一是公有繼承、二是虛擬函式。

3.虛擬函式呼叫方式

通過基類的指標或引用。根據指標指向不同的物件決定呼叫哪個函式。

三、其他知識點總結

1.虛擬函式是動態繫結的基礎。是非靜態的成員函式。

2.virtual只能在宣告的時候使用,實現的時候不能加。

3.具有繼承性。基類中宣告的虛擬函式在派生類中無論是否說明,同原型函式都自動為虛擬函式。

4.虛繼承(不推薦,別用)

為了解決多重繼承而實現的。若D直接繼承B1、B2則A中的引數會在B中出現兩次,浪費空間。使用虛繼承則會節省空間。

class A;

class B1: public virtual A;

class B2: public virtual A;

class D: public B1, public B2;

四、show me code

#include<iostream>
using namespace std;
class A{
    public:
    virtual void foo()
    {
        cout<<"A'foo"<<endl;
        bar();
    }
    virtual void bar()
    {
        cout<<"A's bar"<<endl;
    }
};
class B: public A{
    public:
    virtual void foo()
    {
        cout<<"B'foo"<<endl;
        A::foo();
    }
    virtual void bar()
    {
        cout<<"B's bar"<<endl;
    }
};
int main()
{
    B bobj;
    A *aptr=&bobj;//
    aptr->foo();
    A aobj=*aptr;
    aobj.foo();
}
/*
aptr->foo()輸出結果是:
   B's foo()//這個明白,多型性
   A's foo()//這個也明白,執行A::foo();
   B's bar()// 雖然呼叫的是這個函式:A::foo(); 但隱式傳入的還是bobj 的地址,所以再次呼叫bar();呼叫時還是會呼叫B的函式, 與虛擬函式指標有關

aobj.foo()輸出結果是:
  A's foo() // 這個不是指標,aobj完全是一個A的物件,與多型沒有關係
  A's bar() 
*/