(38.2)虚函数之纯虚函数和抽象类
原创
©著作权归作者所有:来自51CTO博客作者喜欢打篮球的普通人的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
- 1.虚析构函数
- 2.纯虚函数和抽象类
1.虚析构函数
- 派生类的对象从内存中撤销时一般先调用派生类的析构函数, 然后再调用基类的析构函数。
- 但是, 如果用new运算符建立了派生类对象, 且定义了一个基类的指针指向这个对象, 那么当用delete运算符撤销对象时, 系统会只执行基类的析构函数, 而不执行派生类的析构函数, 因而也无法对派生类对象进行真正的撤销清理操作。
- eg:
Point *pp=new Circle; //基类指针指向派生类
delete pp; //仅执行基类析构函数
- 如果希望“delete pp”执行Circle的析构函数, 那么基类Point的析构函数要声明为虚函数, 称为虚析构函数
- 如果将基类的析构函数声明为虚函数, 由该基类所派生的所有派生类的析构函数也都自动成为虚函数, 即使派生类的析构函数与基类的析构函数名字不相同。
- eg:
#include <iostream>
using namespace std;
class Base
{
public:
Base() {}
virtual ~Base() {};
virtual void fun()
{
cout<<"in class Base!"<<endl;
}
};
class Derived:public Base
{
public:
Derived() { };
~Derived()//虚函数
{
cout<<"the destructor of class Derived!"<<endl;
}
void fun()//虚函数
{
cout<<"int class Derived!"<<endl;
}
};
int main()
{
Base *pTest=new Derived;
pTest->fun();//调用派生类fun
delete pTest;//不仅调用基类的析构函数,还调用派生类析构函数
return 0;
}
- 当基类的析构函数为虚函数时, 无论指针指的是同一类族中的哪一个类对象, 系统总会采用动态联编, 调用正确的析构函数, 对该对象进行清理。
- C++支持虚析构函数, 但不支持虚构造函数, 即构造函数不能声明为虚函数。
2.纯虚函数和抽象类
►在许多情况下, 不能在基类中为虚函数给出一个有意义的定义, 这时可以将它说明为纯虚函数(pure virtual function) , 将具体定义留给派生类去做。
纯虚函数的定义形式为:
virtual 返回类型 函数名(形式参数列表)=0;
- 即在虚函数的原型声明后加上“=0” , 表示纯虚函数根本就没有函数体。
- 纯虚函数的作用是在基类中为其派生类保留一个函数的名字, 以便派生类根据需要对它进行定义。
如果在一个类中声明了纯虚函数,而在其派生类中没有对该函数定义, 则该虚函数在派生类中仍然为纯虚函数。 - 包含有纯虚函数的类称为抽象类(abstract class) 。
一个抽象类只能作为基类来派生新类, 所以又称为抽象基类(abstract base class);
抽象类不能定义对象; - 如果在派生类中给出了抽象类的纯虚函数的实现, 则该派生类不再是抽象类。 否则只要派生类仍然有纯虚函数, 则派生类依然是抽象类。
抽象类至少含有一个虚函数, 而且至少有一个虚函数是纯虚函数。 - eg:
#include <iostream>
using namespace std;
class Sharp//Sharp类, 抽象类,不会定义Charp对象
{
public:
virtual double area()=0;//纯虚函数
virtual double volumn()=0;//纯虚函数
};
class Circle:public Sharp//Circle类表示圆
{
public:
Circle(double a):r(a) { }
virtual double area()//虚函数
{
return r*3.1415926*r;
}
virtual double volumn()//虚函数
{
return 0;
}
private:
double r;
};
class Cylinder:public Circle//Cylinder表示圆柱体
{
public:
Cylinder(double a,double b):Circle(a),h(b) { }
virtual double volumn()//虚函数
{
return area()*h;
}
private:
double h;
};
int main()
{
Circle a(10.0);//定义Circle对象
Cylinder b(5.6,10.5);//定义Cylinder对象
cout<<a.area()<<b.volumn()<<endl;//静态联编
Sharp *pb;//定义基类指针
pb=&b;//指向Circle对象
cout<<pb->area()<<","<<pb->volumn()<<endl;//动态联编
return 0;
}