簡體   English   中英

如果基類析構函數是虛擬的,是否需要派生類析構函數定義?

[英]Is a derived class destructor definition required if base class destructor is virtual?

我正在嘗試以下示例:

class base // base class
{
public:
    std::list<base*> values;
    base(){}
    void initialize(base *b) {
        values.push_front(b);
    }
    virtual ~base()
    {
        values.clear();
        cout<<"base called"<<endl;
    }
};

class derived : public base // derived class
{
public:
    ~derived(){
        cout<<"derived called"<<endl;
    }

};

int main()
{
    derived *d = new derived;
    base *b = new base;
    b->initialize(static_cast<base *>(d)); /* filling list */
    delete b;
    return 0;
}

Q.1)為什么不調用派生類的析構函數,因為在基類析構函數中我正在執行values.clear()

Q.2)如果基類析構函數是虛擬的,是否需要派生類析構函數定義?

Q1。 因為您沒有刪除derived類型的對象。 你只做delete b; ,刪除base 你也應該叫delete d;

此外,您應指定負責內存管理的對象。 您的設計容易出錯。 你最好使用智能指針來防止歧義。 此外,為了按照您的預期行事,析構函數應該是:

virtual ~base()
{
    for ( int i = 0 ; i < values.size() ; i++ )
        delete values[i];
    values.clear();
    cout<<"base called"<<endl;
}

當然,使用這種方法,它將是未定義的行為,調用delete d; 在你的main

Q2。 不,這個定義不是必需的。

為什么沒有調用派生類的析構函數,因為在基類析構函數中我正在執行values.clear();

values.clear()從該列表中刪除所有指針。 它不會刪除被指向的對象; 這將是非常危險的,因為該列表無法知道它是否對其生命周期負責,或者它們是否僅用於引用其他地方管理的對象。

如果您希望列表擁有對象,則必須在刪除它們時自行刪除它們,或者存儲智能指針,例如std::unique_ptr<base> 如果您的編譯器不支持新的智能指針,那么您可能會發現Boost的指針容器庫很有用。

是否需要派生類析構函數定義。 如果基類析構函數是虛擬的。

只有在派生類中需要清理的東西時才需要它。 如果沒有什么可以做的話,就沒有必要定義一個空的。

你實際上並沒有delete d ,所以當然沒有調用析構函數。 要么靜態分配d( derived d而不是derived *d = new derived )或調用delete d

如果未在派生類中聲明析構函數,則將創建默認析構函數。 仍將調用基類析構函數,請參閱FAQ (11.12)。 還要注意,由於基類析構函數是虛擬的,派生類析構函數是自動虛擬的(無論您是否定義),請參閱FAQ (20.7)。

為什么你認為應該調用派生類的析構函數? 您只刪除base,它是基類的實例。

不需要析構函數的定義 - 您可以省略它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM