抽象基类和纯虚函数
在设计时,常常希望基类仅仅作为其派生类的一个接口。这就是说,仅想对基类进行向上类型转换,使用它的接口,而不希望用户实际的创建一个基类的对象。
做到这点,可以在基类中加入至少一个纯虚函数(pure virtual function),使得基类称为抽象类(abstract class).
1)纯虚函数使用关键字virtual,并在其后面加上=0。如果试图去实例化一个抽象类,编译器则会阻止这种操作。
2)当继承一个抽象类的时候,必须实现所有的纯虚函数,否则由抽象类派生的类也是一个抽象类。
3)Virtual void fun() = 0;告诉编译器在vtable中为函数保留一个位置,但在这个特定位置不放地址。
建立公共接口目的
建立公共接口目的是为了将子类公共的操作抽象出来,可以通过一个公共接口来操纵一组类,且这个公共接口不需要事先(或者不需要完全实现)。可以创建一个公共类.
虚析构函数
抽象基类不会走子类的析构代码,如果子类申请了堆区内存,需要在抽象基类中加入虚析构,这样就会在析构的时候调用子类的析构函数。
纯虚析构
1)纯虚析构函数在c++中是合法的,但是在使用的时候有一个额外的限制:必须为纯虚析构函数提供一个函数体。
2)如果一个类中有了纯虚析构函数,那么这个类也属于抽象类,无法实例化对象。
如果类的目的不是为了实现多态,作为基类来使用,就不要声明虚析构函数,反之,则应该为类声明虚析构函数。
案列
抽象基类案列
//抽象制作饮品
class AbstractDrinking{
public://烧水virtual void Boil() = 0;//冲泡virtual void Brew() = 0;//倒入杯中virtual void PourInCup() = 0;//加入辅料virtual void PutSomething() = 0;//规定流程void MakeDrink(){Boil();Brew();PourInCup();PutSomething();}
};//制作咖啡
class Coffee : public AbstractDrinking{
public://烧水virtual void Boil(){cout << "煮农夫山泉!" << endl;}//冲泡virtual void Brew(){cout << "冲泡咖啡!" << endl;}//倒入杯中virtual void PourInCup(){cout << "将咖啡倒入杯中!" << endl;}//加入辅料virtual void PutSomething(){cout << "加入牛奶!" << endl;}
};//制作茶水
class Tea : public AbstractDrinking{
public://烧水virtual void Boil(){cout << "煮自来水!" << endl;}//冲泡virtual void Brew(){cout << "冲泡茶叶!" << endl;}//倒入杯中virtual void PourInCup(){cout << "将茶水倒入杯中!" << endl;}//加入辅料virtual void PutSomething(){cout << "加入食盐!" << endl;}
};//业务函数
void DoBussiness(AbstractDrinking* drink){drink->MakeDrink();delete drink;
}void test(){DoBussiness(new Coffee);cout << "--------------" << endl;DoBussiness(new Tea);
}