相信大家都已经清楚了虚函数这个概念。在C++中,构造函数不能声明为虚函数,而析构函数却可以声明为虚函数,大家可能对为什么要把析构函数声明为虚函数很疑惑,下面,云主(博主)就带大家去会会这个虚析构函数
首先,先看一段代码:
#incldue <iostream>
using namespace std;
class Base
{
private:
int *pb;
public:
Base(){ pb = new int(1); } //构造函数
~Base(){ delete pb;
cout<<"Base destructor!!"<<endl;
} //析构函数
};
class Derive : public Base
{
private:
int *pd;
public:
Derive() : Base() { pd = new int(2) }
~Derive(){ delete pd;
cout<<"Derive destructor!!"<<endl;
}
};
int main()
{
Base *p = new Derive();
delete p; //delete时会调用析构函数
return 0;
}
很显然,上面的程序输出结果是:Base destructor!!。
下面,画个图来说明一下
此图适合无虚函数的内存模型,有虚函数时应该再加上虚表指针。
从图中大致可以得出:用基类指针指向派生类对象,此时正常指针可以访问到的是基类自己的成员和虚函数。显然这里在执行语句delete p时,调用的是Base类的析构函数,从而只是释放了pb,而pd仍然在堆中(因为没用调用派生类的析构函数),那么就造成了内存泄露。
如果,将Base类中的析构函数声明为虚函数,即:virtual ~Base(),此时无论派生类中的析构函数有没有加关键字virtual,它都是虚函数。
那么,到这里,我们就清楚了。在delete p时,根据多态的虚表,它调用的是派生类的析构函数,即~Derive(); 而派生类的析构函数会自动调用基类的析构函数。所以,会先释放pd,再释放pb,最后释放p;这样,动态申请的内存的内存就全部被释放了。
小结:若一个类有派生类,则应将这个类设计为多态类。若这个类中没有要设计成多态的成员函数,则至少应该析构函数声明为虚函数。
以上内容是云主学习C++过程中的一些体会。毕竟能力有限,若有错误之处,还望指正: singlecui@126.com