本文讲述的是C++语言中虚函数的理解。
虚函数实现了C++中的“单接口界面,多实现版本”的程序框架。
需要在public或者protected标签下的成员函数前面加上virtual关键字。
例:
#include<iostream>
using namespace std;
class A
{
public:
virtual void display()
{
cout << "class A" << endl;
}
virtual void print(double i)
{
cout << i << endl << "class A" << endl;
}
};
class B : public A
{
public:
virtual void display()
{
cout << "class B" << endl;
}
virtual void print(int i)
{
cout << i << endl << "class B" << endl;
}
};
void show(A *p)
{
p->display();
}
void shownum(A *p)
{
p->print(3);
}
int main()
{
A* pa = new A();
B* pb = new B();
show(pa);
show(pb);
cout << endl << endl;
shownum(pa);
shownum(pb);
}
在代码中,类A和类B中都定义了两个函数print和display,B类继承A类。有一个函数接口show,show函数中的参数是A类的指针。
但是在main函数中pb是B类的指针,show(pb);是可以执行的,而且还调用的是B类的show函数!这就是虚函数的作用,实现单接口界面,多实现版本。
但是呢,在后面的shownum中,虽然输入的是B类的指针,调用的也还是A类的函数,原因就在于调用的print函数中在A类和B类中的定义不一致。虚函数不起作用,调用的还是A类的。
总结:虚函数起作用的条件:完全相同的函数原型(其中包括函数名、参数的个数和类型以及排列顺序)
(为什么shownum(pb)不报错?定义的是A类型指针,却可以用B类型的指针做参数?原因就在于,类的赋值,将派生类的指针赋给基类的指针式可行的,详细说明在上一篇文章C++继承中有讲)
虚函数与函数重载有什么区别?
虚函数是要相同的名字,相同的参数在不同的类中,可以自动选择实现的版本。
函数重载是要相同的名字,不同的参数在相同的类中,可以自动选择实现的版本。
下面介绍一个初学者可能出现的理解失误。
将main函数中的前四句为:
A* pa = new A();
B* pb = new B();
show(pa);
show(pb);
输出结果为Class A和Class B。
若将其替换为如下代码:
B* pb = new B();
A* pa = pb;
show(pa);
show(pb);
与原始代码的区别仅在于pa的定义。此时输出结果为两个Class B,而没有Class A。
如果对此有疑问,请参考C语言指针的定义。
纯虚函数
纯虚函数是指在基类中只有定义没有实现方法,而在派生类中定义实现方法的虚函数。方法是要在后面加上=0。例:
virtual float area( ) = 0;
不同点就是多了等于0。
抽象类
抽象类是用来描述概念性的类,里面都是虚函数,并没有实现方法。被继承后才定义实现方法。一般就是用于提供通用接口。