C++中虚函数实现父类函数多态性
今天项目用到了策略设计模式,其中需要实现子类函数的多态性,先总结复习一下。
一、小例子
话不多说,先上例程。
#include <iostream>
using namespace std;
class Mouse{
public:
/**
* 虚函数 带有实现
*/
virtual void click(){
cout<<"Mouse is clicked!"<<endl;
};
/*
* 纯虚函数 表明Mouse为抽象类
*/
virtual void print()=0;
};
class OpticalMouse : public Mouse{
/**
* 未重写虚函数
*/
virtual void click();
/**
* 实现纯虚函数
*/
virtual void print(){
cout<<"This is an OpticalMouse."<<endl;
};
};
class MechanicalMouse : public Mouse{
/**
* 未重写虚函数
*/
virtual void click();
/**
* 实现纯虚函数
*/
virtual void print(){
cout<<"This is a mechanical Mouse."<<endl;
};
};
int main(int argc, char **argv) {
Mouse* myMouse;
myMouse = new OpticalMouse;
myMouse->click();
myMouse->print();
return 0;
}
编译时会报错 如下图所示:
错误为: “undefined reference to ‘vtable for ×××’”,这个问题主要是由于子类调用了父类的虚函数,在子类中没有定义导致的虚拟函数表出现未定义错误。将程序修改如下:
class OpticalMouse : public Mouse{
/**
* 未重写虚函数
*/
virtual void click(){
cout<<"Optical Mouse is clicked."<<endl;
};
/**
* 实现纯虚函数
*/
virtual void print(){
cout<<"This is an OpticalMouse."<<endl;
};
};
重新运行,得到结果:
Starting: /home/xxdk/projects/virDemo/build/virdemo
Optical Mouse is clicked.
This is an OpticalMouse.
*** Exited normally ***
说明用父类的指针可以完成子类虚函数的调用,从而实现运行时多态。
二、虚函数的机制
虚函数是一种动态绑定机制,其中有两个主要概念:vtable和vptr。
具体过程为:每一个内含虚拟函数的类,编译器都会为它做出一个虚拟函数的表vtable,表中的元素指向一个虚拟函数的地址。编译器会为类别加上个成员变量,是一个指向该虚拟函数表的指针vptr。
子类会继承基础类别的虚拟函数表,如上例所示,如果对于虚拟函数子类有同名的虚拟函数的话,就会覆盖原父类的虚拟函数地址,从而达到通过指向父类的指针调用了子类的虚拟函数的功能,从而实现多态。但是如果子类的虚拟函数没有实现的话就会出现上面说的undefined reference to ‘vtable for ××ב的错误。
三、虚函数的使用
如上所述,为了使程序能够实现多态的功能,应该在子类中实现父类的虚函数。为了更显式地达到这个效果,在父类中应使用纯虚函数来完成。即令虚函数=0,这样在子类中必须实现所有纯虚函数才能使类实例化,而用指向父类的指针则可以顺利地使用子类的函数,从而达到多态化的效果。