析构函数为什么要定义成虚函数

结论:

  实现多态时,我们通过基类指针指向子类对象,在delete基类指针时,我们希望先调用子类的析构函数,再调用父类的析构函数,要实现这个目的,析构函数就必须定义成虚函数,否则只会调用父类的析构函数,子类的析构函数不会被调用。

 

实验1:析构函数不定义成虚函数

#include <iostream>

using namespace std;

class father {
public:
    father(int num) {
        cout << "create father" << endl;
        // new申请的内存不用判空,new不到内存会抛出异常,不会返回空指针
        father_ptr = new int(num);
    }

    ~father() {
        cout << "destory father" << endl;
        if (father_ptr != nullptr) {
            delete father_ptr;
        }
        // 释放内存以后,一定记得置空,防止出现野指针
        father_ptr = nullptr;
    }

private:
    int *father_ptr;
};

class child : public father {
public:
    // 父类没有无参构造函数,需要显示调用父类构造函数
    child(int x, int y) : father(x) {
        cout << "create child" << endl;
        child_ptr = new int(y);
    }

    ~child() {
        cout << "destory child" << endl;
        if (child_ptr != nullptr) {
            delete child_ptr;
        }
        child_ptr = nullptr;
    }

private:
    int *child_ptr;
};

int main()
{
    father *ptr = new child(10, 20);
    delete(ptr);
    return 0;
}

运行结果:结果说明不定义成虚函数,只会调用父类的析构函数,不会调用子类的析构函数,导致内存泄露。

 

实验2:析构函数定义成虚函数

#include <iostream>

using namespace std;

class father {
public:
    father(int num) {
        cout << "create father" << endl;
        // new申请的内存不用判空,new不到内存会抛出异常,不会返回空指针
        father_ptr = new int(num);
    }

    virtual ~father() {
        cout << "destory father" << endl;
        if (father_ptr != nullptr) {
            delete father_ptr;
        }
        // 释放内存以后,一定记得置空,防止出现野指针
        father_ptr = nullptr;
    }

private:
    int *father_ptr;
};

class child : public father {
public:
    // 父类没有无参构造函数,需要显示调用父类构造函数
    child(int x, int y) : father(x) {
        cout << "create child" << endl;
        child_ptr = new int(y);
    }

    virtual ~child() {
        cout << "destory child" << endl;
        if (child_ptr != nullptr) {
            delete child_ptr;
        }
        child_ptr = nullptr;
    }

private:
    int *child_ptr;
};

int main()
{
    father *ptr = new child(10, 20);
    delete(ptr);
    return 0;
}

运行结果:父类和子类都正常析构了。

 

 

tips:良好的编程习惯,不管类中有没有指针,有没有动态申请内存,都应该把析构函数定义成虚函数,定义成虚函数总是不会错的。

 

posted @ 2021-04-26 19:59  我是团长  阅读(1308)  评论(0编辑  收藏  举报