在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。
纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时再去具体地给出定义。凡是含有纯虚函数的类叫做抽象类。这种类不能声明对象,只是作为基类为派生类服务。除非在派生类中完全实现基类中所有的的纯虚函数,否则,派生类也变成了抽象类,不能实例化对象。
记住:
有纯虚函数的类是抽象类,抽象类不可以实例化.
继承纯虚函数的子类 若不实现纯虚函数,则也是抽象类.
记住:
希望子类各自实现这个方法(而不是有侥幸心理即使不实现也可以调用父类的函数)时使用纯虚函数
#include <iostream>
using namespace std;
//拥有纯虚函数的类是抽象类 不允许创建抽象类的对象 但可以用抽象类的指针或者引用指向子类对象
class Animal
{
public:
Animal(){} //构造函数没必要使用虚函数
virtual ~Animal(){} //每个对象结束时都要调用析构函数 ,析构不能定义为纯虚函数
void play() //在普通函数中调用虚函数
{
eat();
shout();
sleep();
}
//纯虚函数 保证子类必须要实现 在java中称为interface
virtual void eat() =0;
virtual void shout() =0;
virtual void sleep() =0;
};
class Horse:public Animal
{
//当将基类中的某一成员函数声明为虚函数后,派生类中的同名函数自动成为虚函数。
//访问权限也是和父类中相同的 public 和 virtual 都是可写可不写的
public:
Horse(){cout << "一匹马" <<endl; }
~Horse(){cout << "马死了" <<endl;}
virtual void eat() {cout << "吃草" << endl;}
virtual void shout() {cout << "嘶~" <<endl;}
virtual void sleep() {cout << " 站着睡" <<endl;}
};
class Tiger:public Animal
{
public:
Tiger(){cout << "一只老虎"<<endl;}
~Tiger() {cout<< "死老虎" <<endl;}
virtual void eat() {cout << "吃肉" << endl;}
virtual void shout() {cout << "吼~" <<endl;}
virtual void sleep() {cout << "趴着睡" <<endl;}
};
int main()
{
//不能创建抽象类对象
// Animal a; //error: cannot declare variable ‘a’ to be of abstract type ‘Animal’
Animal *p = NULL;
// p = new Animal; //cannot allocate an object of abstract type ‘Animal’
char n;
cout << "输入选项 h--马 t--老虎" <<endl;
cin >> n;
if(n == 'h')
p = new Horse;
else
p = new Tiger;
p->play();
delete p; //需要将p的析构设置为虚函数 才可以调用子类的虚函数
}
/*
1 一般函数 不希望子类去改变
2 普通虚函数 希望子类可以覆盖这个函数 构造自己的实现
3 纯虚函数 子类操作各不相同,要求每个子类必须自己实现
4 静态成员函数 该函数的操作不依赖具体的对象
*/