zoukankan      html  css  js  c++  java
  • C++虚析构函数

    我知道,对于存在虚函数的基类,一般需要将基类的析构函数定义为虚函数,从而实现资源的合理释放,而且我也知道派生类在重载时,只需要清理自己的对象,不过,有时候还是会有些疑惑感,所以写了一个简单的例子,来消除疑惑。下面是实例内容:

    #include <iostream>
    
    class student
    {
    public:
        student() {}
        ~student() { std::cout << "a student" << std::endl; }
    };
    
    class bachelor
    {
    public:
        bachelor() {}
        ~bachelor() { std::cout << "a bachelor" << std::endl; }
    };
    
    class studentHolder
    {
    public:
        studentHolder()
        {
    
        }
    
        virtual ~studentHolder() {}
    
    
    private:
        student st;
    };
    
    class bachelorHolder : public studentHolder
    {
    public:
        bachelorHolder()
            : studentHolder()
        {
    
        }
    
        ~bachelorHolder() override
        {
    
        }
    
    private:
        bachelor bcl;
    };

    下面是调用的地方的代码:

    #define _CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>
    
    int main()
    {
        _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
        studentHolder* holder = new bachelorHolder();
        delete holder;
        return 0;
    }

    这种情况下,会执行正确的清理操作:

    这种情况下,如果将bachelorHolder中的析构函数删除,即:

    class bachelorHolder : public studentHolder
    {
    public:
        bachelorHolder()
            : studentHolder()
        {
    
        }
    
    private:
        bachelor bcl;
    };

    这种情况下,对象依然被很好的清理,因为C++会默认为类创建一个析构函数,而且如果基类为虚函数,派生类创建的为重写基类的虚函数。结果依然是:

    如果在上述的情况下,将studentHolder析构函数的virtual移除,即:

    class studentHolder
    {
    public:
        studentHolder()
        {
    
        }
    
        ~studentHolder() {}
    
    
    private:
        student st;
    };

    结果将变成:

    不过,注意一点,这里,只是说派生类的析构函数没有被调用,资源(分配的堆内存)还是会被很好的释放。这里,可以查看,如果我们将main函数中的delete holder;注释掉:

    int main()
    {
        _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
        studentHolder* holder = new bachelorHolder();
        // delete holder;
        return 0;
    }

    在debug模式下,进行调试,会在output窗口,得到如下结果:

    而就算将main函数,改为如下:

    int main()
    {
        _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
        studentHolder* holder = new bachelorHolder();
        delete reinterpret_cast<void*>(holder);
        return 0;
    }

    在output窗口,都不会出现内存泄漏的显示。大致内容就是上述显示,在有疑虑的时候,可以参考一下。

  • 相关阅读:
    如何:在 DataGrid 控件中对数据进行分组、排序和筛选
    转载:一站式WPF依赖属性(DependencyProperty)
    转载:WPF 善用路由事件
    Tomcat内存溢出
    Postgresql允许远程访问配置修改
    python笔记2
    我怀念的
    OpenCV第二个assignment:检测QR code的3个 finder centers
    学期总结
    机器视觉课程的第一个assignment——OpenCV
  • 原文地址:https://www.cnblogs.com/albizzia/p/8979078.html
Copyright © 2011-2022 走看看