文章目录

  • ​​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;
}