析構函數為什么要定義成虛函數


結論:

  實現多態時,我們通過基類指針指向子類對象,在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:良好的編程習慣,不管類中有沒有指針,有沒有動態申請內存,都應該把析構函數定義成虛函數,定義成虛函數總是不會錯的。

 


免責聲明!

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



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