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


    结论:

      实现多态时,我们通过基类指针指向子类对象,在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:良好的编程习惯,不管类中有没有指针,有没有动态申请内存,都应该把析构函数定义成虚函数,定义成虚函数总是不会错的。

    https://i.cnblogs.com/posts?categoryid=0
  • 相关阅读:
    Python--网络编程
    Linux-安装Windows字体
    计算机网络基础
    Cobalt Strike之CHM、LNK、HTA钓鱼
    Python之——python-nmap的安装与常用方法说明
    Python之单例模式的多种实现
    Cobalt Strike之信息收集、木马钓鱼
    Ubuntu 16.04安装Java 8
    代码审计-MetInfo 6.0.0 sql注入漏洞
    代码审计-凡诺CMS 2.1文件包含漏洞
  • 原文地址:https://www.cnblogs.com/418ks/p/14706243.html
Copyright © 2020-2023  润新知