上一篇博文我们提到,多态的分类可分为:编译时多态(静态绑定)、运行时多态(动态绑定),本篇就是讲解实现动态绑定的虚函数问题。
首先,虚函数必须存在于类的继承环境之中才有意义,声明函数的方法很简单,只要在积累的成员函数名前加上关键字virtual即可,格式如下:
class 类名
{
...
virtual 函数类型 成员函数名(参数表)
...
}
当一个类的成员函数被声明为虚函数后,就可以在该类的派生类中定义与其基类虚函数原型完全相同的函数。此时,当用基类指针指向这些派生类对象时,系统会自动用派生类同名函数来代替基类中的虚函数
也就是说,当用积累指针指向不同个派生类对象时,系统在程序运行中根据所指向的对象不同,自动选择适当的函数,从而实现了运行时的多态性。
那么,虚函数到底是怎样实现动态绑定的呢?我们来看这段代码
首选我们来看虚函数的定义,在基类中:
class Base{ //基类
public:
virtual void Print(){ //函数类型前加virtual即声明为虚函数
cout << "Base Class Print!" << endl;
}
};
基类的派生类的继承和定义都同静态绑定是一样的,我们来看具体的实现(对静态绑定在灵活性上进行改进)
我们对代码进行逐段分析:
Base b1, *pb; //定义基类对象和指针
Derived1 d1; //定义派生类1的对象
Derived2 d2;
Base &rb1 = b1; //定义基类对象b1的对象引用rb1
pb = &b1; //基类指针指向基类对象b1
pb->Print(); //用指针调用成员函数
rb1.Print(); //用基类引用调用接力对象成员函数
那么这段代码的运行结果是怎样的:
当我们已经把基类的成员函数声明为虚函数后,我们定义了一个基类的指针pb和引用rb1,然后pb指针和rb1引用都指向了基类的对象b1,所以调用基类的Print()函数,输出结果为:
Base Class Print!
Base Class Print!
再看这个
pb = &d1; //基类指针指向派生类Derived1的对象d1
pb->Print(); //用接力指针pb调用派生类虚函数对象
pb = &d2; //基类指针指向派生类Derived2的对象d2
pb->Print(); //用基类指针pb调用派生类虚函数
同上,基类指针分别指向了派生类Derived1的对象d1和派生类Derived2的对象d2,所以,这段代码的输出结果为:
Derived1 Class Print!
Derived2 Class Print!
最后一段是:
Base &rb2 = d1; //定义派生类的对象d1的基类引用rb2
rb2.Print(); //用基类引用rb2调用派生类对象d1的成员函数
此处定义的基类引用相当于指向了派生类Derived1的对象d1,所以输出结果为:
Derived1 Class Print!
完整代码如下:
//created by kong at 2019-10-21
#include<iostream>
using namespace std;
class Base{ //基类
public:
virtual void Print(){ //声明为虚函数
cout << "Base Class Print!" << endl;
}
};
class Derived1 :public Base{ //第一个共有派生类Derived1
public:
void Print(){
cout << "Derived1 Class Print!" << endl;
}
};
class Derived2 :public Base{ //第二个共有派生类Derived2
public:
void Print(){
cout << "Derived2 Class Print!" << endl;
}
};
int main(){
Base b1, *pb;
Derived1 d1;
Derived2 d2;
Base &rb1 = b1; //定义基类对象b1的对象引用rb1
pb = &b1; //基类指针指向基类对象b1
pb->Print(); //用指针调用成员函数
rb1.Print(); //用基类引用调用接力对象成员函数
pb = &d1; //接力指针指向派生类Derived1的对象d1
pb->Print(); //用接力指针pb调用派生类虚函数对象
pb = &d2; //基类指针指向派生类Derived2的对象d2
pb->Print(); //用基类指针pb调用派生类虚函数
Base &rb2 = d1; //定义派生类的对象d1的基类引用rb2
rb2.Print(); //用基类引用rb2调用派生类对象d1的成员函数
return 0;
}
运行结果:

本文详细解析C++中虚函数的概念与实现,通过实例演示如何利用虚函数实现动态绑定,达到运行时多态的目的。
898

被折叠的 条评论
为什么被折叠?



