C++编程入门--动态绑定虚函数

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

上一篇博文我们提到,多态的分类可分为:编译时多态(静态绑定)、运行时多态(动态绑定),本篇就是讲解实现动态绑定的虚函数问题。
首先,虚函数必须存在于类的继承环境之中才有意义,声明函数的方法很简单,只要在积累的成员函数名前加上关键字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;
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值