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窗口,都不會出現內存泄漏的顯示。大致內容就是上述顯示,在有疑慮的時候,可以參考一下。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM