首先:强调一个概念
定义一个函数为虚函数,不代表函数为不被实现的函数。
定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。
定义一个函数为纯虚函数,才代表函数没有被实现。
定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
我们首先举一个例子,如下所示
class A
{
public:virtual void foo(){cout<<"A::foo() is called"<<endl;}
};
class B:public A
{
public:void foo(){cout<<"B::foo() is called"<<endl;}
};
int main(void)
{A *a = new B();a->foo(); // 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的!return 0;
}
虚函数只能借助于指针或者引用来达到多态的效果。这个时候我们就疑惑了,为什么要用父类指针指向子类对象呢?直接定义子类对象不好吗?
那么这里我来说一个场景,你接到老板的任务,需要使用厂家的SDK实现一个功能,而厂家的一个put函数是私有的,而是这个函数和你的使用场景有些不同,需要重写。而你首先继承了厂家的Father的类,然后重写了Put函数,结果运行不是你想要的。
#include<iostream>
using namespace std;class Father
{void Put(){cout<<"父类Put函数"<<endl;}
public:void Show(){Put();}
};class Son:public Father
{void Put(){cout<<"子类Put函数"<<endl;}
};int main()
{Son a;a.Show();
}
运行结果为:父类Put函数
这个时候你又要重写一个show函数,上述代码还算简单,如何代码间耦合嵌套比较深,那么就相当于重新写了一个新的类,而不需要继承了,这样就显得麻烦了。
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加 =0:
virtual void funtion1()=0
为什么要这样呢?
为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。
声明了纯虚函数的类是一个抽象类。所以,用户不能创建类的实例,只能创建它的派生类的实例。
纯虚函数最显著的特征是:它们必须在继承类中重新声明函数(不要后面的=0,否则该派生类也不能实例化),而且它们在抽象类中往往没有定义。