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类中的虚函数;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章