C++ virtual虛函數

1. 爲什麼要使用虛函數?

  • 在C++語言中,基類將類型相關的函數與派生類不做改變直接繼承的函數區分對待,對於某些函數,基類希望它的派生類各自定義適合自身的版本,此時基類就將這些函數聲明成虛函數
  • 虛函數使用virtual關鍵字表示,如下面程序中Parent類中的Function2就是虛函數
  • 基類中定義的虛函數必須在其派生類中有和其完全相同的函數聲明(函數名、參數列表,返回值),使用override關鍵字,表示該函數可能會覆蓋基類中對應的虛函數。

2. 看一個例子

#include <iostream>

using namespace std;
class Parent
{    
 public:
    char data[20];
    void Function1(){
         printf("This is parent,function1\n");
    }
     // 這裏聲明Function2是虛函數
     virtual void Function2() {
         printf("This is parent,function2\n");
    }  
     
}parent;
class Child:public Parent
{
     void Function1(){
        printf("This is child,function1\n");
     }
     void Function2() override{
        printf("This is child,function2\n");
     }
     
}child;
int main(int argc, char* argv[])
{
    int a;
    Parent *p;  // 定義一個基類指針
    scanf("%d",&a);
    if(a)    // 如果輸入1   
        p=&child;        // 指向繼承類對象
    else    // 如果輸入0
        p=&parent;       // 否則指向基類對象
    p->Function1();  // 這裏在編譯時會直接給出Parent::Function1()的入口地址。    
    p->Function2();  // 注意這裏,執行的是哪一個Function2?
    return 0;
}
  • 運行結果:
  • 如果鍵盤輸入1,則:
1
This is parent,function1
This is child,function2
  • 如果鍵盤輸入0,則:
0
This is parent,function1
This is parent,function2

一句概括的話:當使用基類的指針或引用調用虛函數時,會發生動態綁定,即該指針或引用可能綁定一個基類對象,也可能綁定一個派生類對象,這在函數運行的時候才能得知。如果綁定的是基類對象,則調用的是基類中的虛函數,如果綁定的是派生類對象,則調用的是派生類中的虛函數

3. 動態綁定和靜態綁定的概念

  • 靜態綁定:對於引用或指針,在編譯過程中就已經綁定了對象;
  • 動態綁定:對於引用或指針,在編譯過程中不知道該綁定什麼對象,只有在運行時才進行綁定;

注意:當且僅當基類的指針或引用調用虛函數時,纔會發生動態綁定

  • 因此,上面主程序中p->Function1();調用Function1時,由於Function1不是虛函數,因此不會發生動態綁定。在編譯時,p就已經綁定了其聲明的對象Parent類,因此其調用的自然是Parent中的Function1;
  • p->Function2();調用Function2時,由於Function2是虛函數,因此發生動態綁定。編譯時,p不會綁定任何對象,在運行時,如果p綁定了Parent對象,則調用的是Parent類中的虛函數,如果綁定了Child對象,則調用的是Child類中的虛函數;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章