天天看點

C++(多态實作原理)函數重寫,重載,重定義

多态的實作原理:

         首先介紹下函數重寫 重定義 重載的差別;

函數重寫:

         發生在父類和子類之間,子類将父類中的同名函數進行了覆寫,如果在函數前面含有virtual那麼就是重寫,如果沒有就成了覆寫,子類的同名函數将會覆寫(隐藏)父類的同名函數,如果想調用的話,那麼就要使用::作用域運算符

函數重載:

         函數重載發生在同類之間,平等關系。在不同的類對函數看似重載的操作是不成立的

多态理論基礎:

         靜态聯編:

         是程式的比對,連接配接在編譯階段實作,也成為早起比對,重載使用的就是靜态聯編

動态聯編譯:

         是指程式聯編推遲到運作時進行,又成為遲綁定

在編譯階段,編譯器自動根據指針的類型判斷是執行的父類對象還是子類對象:出于程式安全的角度講,編譯器認為父類指針指向父類對象,子類指針指向子類對象。這就是靜态聯編的結果

(一)談談你對多态的了解?

答:

1.      多态的實作效果,同樣的調用語句有不同的表現形态:

2.      多态實作有三個條件?

有繼承,有虛函數重寫,有父類指針指向子類對象:

3.      Virtual關鍵字告訴編譯器這個函數支援多态,不要根據指針的類型進行調用,而是根據指針所指向的具體的對象,進行函數調用

4.      理論基礎:

動态聯編PK靜态聯編,根據實際的對象的類型來判斷重寫函數的調用

5.      多态的重要意義:

設計模式的基礎,是代碼架構的基石

(二)是否每個類的成員函數都聲明為虛函數,為什麼??

答.可以聲明為虛函數,但是在在定義對象的時候,會生成一個虛函數表,而虛函數在調用的時候是通過尋址實作的,這回影響代碼的執行效率

(三)構造函數中調用虛函數能實作多态嗎?

答.不可以,因為多态的vptr指針是分布初始化的,在子類進行初始化的時候先調用父類的構造函數,這時候子類的父類的Vptr指針都是指向父類的,是以産生不了多态。

(四)為什麼要定義虛析構函數?

答.因為virtual可以指引delete運算符正确析構動态對象

是這樣的,當發生多态的時候,基類指針指向派生類,當釋放記憶體的時候,編譯器根據指針類型去調用相應的函數,由于是基類指針,那麼隻會去調用基類對象的析構

函數,進而導緻發生多态的子類對象的析構函數不能正常執行,但是當聲明為虛析構的時候就能正常使用了,父類析構函數virtual,子類進行重寫,那麼就可以正常的進行析構了。

(五)重點:

         就是基類指針指向父類對象還是子類對象???我們在分析的時候是這麼分析的,如果基類指針指向父類對象,那麼就去調用父類的對象;如果指向子類對象,就去調用子類對象。

  靜态聯編:是編譯根據指針類型進行對象的确定;   動态聯編譯是根據,指針指向的對象進行函數調用,(要含有虛函數,如果沒有虛函數是不是要報錯(是以産生了dynamic_cast< >這個東東進行運作時類型檢查))

         但是實際情況是這樣的,編譯器壓根就不是這麼做的。而是根據傳遞來的是什麼對象,然後看此函數是否是虛函數,如果是虛函數,就去找這個對象對應的虛函數表,然後調用相應的函數。

實作了重載或重寫的函數,如果想在子類中調用父類的函數,那麼可以使用(類名::函數名 ) 的方式來通路父類中的函數

#include<iostream>

using namespace std;

class AA{

public:

    int add(int a,int b){

        return a + b;

    }

    virtual int sub(int a,int b){

        return a - b;

    }

};

class BB :public AA{

public:

    int add(int a, int b){

        return a + b +10;

    }

    virtual int sub(int a, int b){

        return a - b -10;

    }

};

void main(){

    int a = 100, b = 100;

    BB bb;

    AA aa;

    int c = aa.add(a, b);//200

    cout << c  << endl;

    c = bb.add(a, b);//210

    cout << c << endl;

    c = bb.AA::add(a, b);//200

    cout << c << endl;

    c = bb.sub(a, b);//-10

    cout << c << endl;

    c = bb.AA::sub(a, b);//0

    cout << c << endl;

    system("pause");

}

c++

繼續閱讀