天天看點

virtual 析構函數

轉載位址:http://blog.chinaunix.net/uid-25808509-id-3026857.html

有時候我們需要用基類的指針删除其子類的對象,這時候要非常注意,倘若基類的析構函數是 non-virtual析構函數,那麼事實上,隻有基類的析構函數被調用,派生類的析構函數并沒有被調用,這可能會導緻資源洩漏。為避免這中情況發生,我們可以将基類的析構函數聲明為virtual,這樣的話,子類對象才能被完全銷毀.

#include <iostream>
#include <stdlib.h>
#include <crtdbg.h>

#ifdef _DEBUG
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

using namespace std;

class BaseClass
{
public:
    virtual ~BaseClass() = 0;
    //~BaseClass();
};

BaseClass::~BaseClass()
{
    cout << "the ~BaseClass is called" << endl;
}

class DerivedClass : public BaseClass
{
public:
    DerivedClass(int x, int y)
        :X(x)
        ,Y(y)
    {
        a = new int[y];
    }

    ~DerivedClass()
    {
        cout << "the ~Derivedclass is called" << endl;
        if(a)
        {
            delete a;
            a = NULL;
        }
    }


private:
    int X;
    int Y;
    int *a;
};

void main()
{
    //memory check
    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

    BaseClass *bs= new DerivedClass(2, 3);

    delete bs;

    system("pause");

}
           

程式運作結果為

the ~Derivedclass is called

the ~BaseClass is called

基類和派生類的析構函數都被調用

倘若基類的析構函數為~BaseClass();即 non-virtual 析構函數,

程式運作結果為

the ~BaseClass is called,

隻有基類的析構函數被調用,子類中指針 a 指向的記憶體并沒有被釋放

Dumping objects ->

e:\work\test\test\test.cpp(287) : {128} normal block at 0x00395E38, 12 bytes long.

 Data: <            > CD CD CD CD CD CD CD CD CD CD CD CD 

Object dump complete.

12 位元組的記憶體洩漏了

是以,隻有當一個類被用來作為基類的時候,才會把析構函數寫成虛函數。

繼續閱讀