纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时再去具体地给出定义。凡是含有纯虚函数的类叫做抽象类。这种类不能声明对象,只是作为基类为派生类服务。除非在派生类中完全实现基类中所有的的纯虚函数,否则,派生类也变成了抽象类,不能实例化对象。
定义虚函数是为了允许用基类的指针来调用子类的这个函数。定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
问题:抽象类不能实例化,可否定义为派生类的指针呢?
- #include<iostream>
- using namespace std;
- class base{
- public:
- //virtual base(){}//构造函数不能声明为虚函数,编译错误
- virtual void show()=0;
- void fun(){
- cout<<"base::fun()"<<endl;
- }
- //virtual ~base()=0;//将析构函数声明为纯虚函数必须在类外定义入16行,为什么要这样?有些时候基类里面没有合适的函数作为纯虚函数使基类作为抽象类,所以让析构函数作为纯虚函数是变废为宝,但是纯虚析构必须定义体16行。通常的纯虚函数不需要函数体但不代表不可以有。虚析构函数工作的方式是:最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。
- virtual ~base(){//虚析构才能将派生类
- //~base(){//非虚析构
- cout<<"~base()"<<endl;
- }
- };
- //base::~base(){}//纯虚析构体
- void base::show(){cout<<"函数体"<<endl;}//virtual关键字就不再出现了,事实证明纯虚函数可以有体,只不过没什么用罢了,直接被编译器忽视,通过运行使动态绑定直接执行派生类的重写函数
- class derived:public base{
- public:
- virtual void show(){
- cout<<"derived::show()"<<endl;
- }
- void fun(){
- cout<<"derived::fun()"<<endl;
- }
- ~derived(){
- cout<<"~derived"<<endl;
- }
- };
- int main(){
- //base* p=new base;//实例化抽象类,编译错误
- base* one=new derived;//可以使用基类指针,由于抽象类不能实例化所以只能用派生类的对象了
- one->show();//derived::show() 函数重写
- one->fun();//base::fun() 函数隐藏
- delete one;
- return 0;
- }
基类base的析构函数不申明为virutal时的输出:
derived::show()
base::fun()
~base() //可见并未清理派生类对象
基类base的析构函数为virutal时的输出:
derived::show()
base::fun()
~derived //此时派生类对象被析构
~base()
基类base的析构函数为纯虚函数时的输出:
derived::show()
base::fun()
~derived //由于基类为纯虚析构,所以只有派生类打印,但是基类析构还是进行了的