3.虚析构函数

点击打开在线编译器,边学边练

虚析构函数

 

在C++中,不能把构造函数定义为虚构造函数,因为在实例化一个对象时才会调用构造函数,且虚函数的实现,其实本质是通过一个虚函数表指针来调用的,还没有对象更没有内存空间当然无法调用了,故没有实例化一个对象之前的虚构造函数没有意义也不能实现。

 

但析构函数却是可以为虚函数的,且大多时候都声明为虚析构函数。这样就可以在用基类的指针指向派生类的对象在释放时,可以根据实际所指向的对象类型动态联编调用子类的析构函数,实现正确的对象内存释放。

 

下面我们做一个实验,请看代码:

 

/**************************************
//Des:C++教程demo
//Author:Huang
//Copyright:www.dotcpp.com
//Date:2017/12/27
**************************************/
#include <iostream>
using namespace std;
class Point
{
private:
    int x,y;
    int *str;
 
public:
    Point(int x=0,int y=0)
    {
        this->x = x;
        this->y = y;
        str = new int[100];
    }
    ~Point()
    {
        delete []str;
        cout<<"Called Point's Destructor and Deleted str!"<<endl;
    }
 
 
};
class Circle:public Point
{
private:
    int r;
    int *str;
public:
    Circle(int x,int y,int R):Point(x,y)
    {
        r = R;
        str = new int[100];
    }
    ~Circle()
    {
        delete []str;
        cout<<"Called Circle's Destructor and Deleted str!"<<endl;
    }
 
};
 
 
 
int main()
{
 
    Point *p;
    p = new Circle(10,10,20);
    delete p;
 
    return 0;
 
}

 

可以看到代码,基类中没有用virtual声明的析构函数,且基类和派生类当中都有动态内存开辟,那么我们在主函数中也动态开辟内存的方式创建一个Circle类,然后删除

之后运行后截图如下:

6031.png


可以清楚的看到,仅仅调用了基类的析构函数,这样一来派生类中new出来的4*100字节的内存就会残留,造成内存泄漏!

 

而如果把基类中析构函数声明为virtual,则结果大有不同!这个时候多态效应出现,会先调用释放派生类的空间,然后再释放基类的内存空间,完美结束,如下图:


6032.png


以上,这就是虚析构函数带来的好处,大家自行体会。