• C++ 虚析构函数


    为什么基类需要虚析构函数?下面给出一个例子

    #include <iostream>
    using namespace std;
    class A{
        public:
        ~A(){ cout << "~A()" << endl; }
        //virtual ~A(){ cout << "~A()" << endl; }
    };
    
    class B : public A{
        ~B(){ cout << "~B()" << endl; }
    };
    
    int main()
    {
        A* p = new B;
        delete p;
    }

    编译:g++ -Wall ./v-deconstr.cpp

    执行:~A()

    会发现,析构函数只调用了基类的析构函数,派生类没有被析构。原因个人理解就是由于p是指向A的指针,会有up casting,导致delete p时,调用A的析构函数。

    #include <iostream>
    using namespace std;
    class A{
        public:
        //~A(){ cout << "~A()" << endl; }
        virtual ~A(){ cout << "~A()" << endl; }
    };
    
    class B : public A{
        ~B(){ cout << "~B()" << endl; }
    };
    
    int main()
    {
        A* p = new B;
        delete p;
    }

    Class A的析构函数改为虚函数,在编译执行结果为:

    ~A()
    ~B()

    这样析构才是正确的,把派生类和基类的析构函数都调用,释放正确。

    如果是

    B *pB = new B;
    delete pB;

    输出则是
    ~B()
    ~A()

    原因分析:

    pB是静态的,析构的时候,因此会依次调用~B,~A。
    但p是A类型的,在使用delete时如果A的析构函数不是虚函数,则会只调用A的析构函数,造成子类的内存泄露;
    而如果A的析构函数是虚函数,由于存在动态绑定,并且通过指针或者引用,存在派生类向基类转换则,delete会在调用完~A,发现~A是虚函数,再调用~B,完成全部的析构。

     

  • 相关阅读:
    2. Redis哨兵、复制、集群的设计原理与区别
    1. 详解Redis的存储类型、集群架构、以及应用场景
    博客园主题优化
    【Java基础】Java面试题精选
    【Java集合】——集合类分析总结
    新零售供应链的三大闭环
    Comparable和Comparator比较实现排序 场景分析
    Java基础-枚举类
    Java基础-泛型
    微服务架构~BFF和网关
  • 原文地址:https://www.cnblogs.com/tingjie-word/p/7843023.html
Copyright © 2020-2023  润新知