根據這篇文章,它說[強調我的]:
使基類解構式為虛擬可以保證派生類的物件被正確析構,即基類和派生類解構式都被呼叫。
作為指導,任何時候你在一個類中有一個虛函式,你應該立即添加一個虛解構式(即使它什么都不做)。這樣,您可以確保以后不會出現任何意外。
我認為即使您的基類沒有虛函式,您也應該添加一個虛擬解構式或將基類的解構式標記為受保護。否則,在嘗試delete指向派生實體的指標時,您可能會遇到記憶體泄漏。我對嗎?
例如,這里是演示代碼片段:
#include<iostream>
class Base {
public:
Base(){};
~Base(){std::cout << "~Base()" << std::endl;};
};
class Derived : public Base {
private:
double val;
public:
Derived(const double& _val){};
~Derived(){std::cout << "~Derived()" << std::endl;}; //It would not be called
};
void do_something() {
Base* p = new Derived{1};
delete p;
}
int main()
{
do_something();
}
這是上述代碼片段的輸出:
~Base()
有人可以對此事有所了解嗎?
uj5u.com熱心網友回復:
問題中程式的行為未定義。它通過指向其基型別的指標洗掉派生型別的物件,并且基型別沒有虛擬解構式。所以不要那樣做。
有些人喜歡撰寫具有額外開銷的代碼,以“確保以后不會出現任何意外”。我更喜歡撰寫能滿足我需求的代碼并記錄它的功能。如果我以后決定我需要它做更多的事情,我可以改變它。
uj5u.com熱心網友回復:
這個問題將導致一系列其他問題,即程式員是否應該通過保護其代碼,即使是當前不存在的問題,也應該始終保持超級安全。
在您當前的代碼中,該類僅向其基類Derived添加了一個微不足道的內容,以及一個相當無用的解構式,它僅包含跟蹤列印。如果你通過指向基類的指標洗掉了一個物件,解構式不會被呼叫,但它是無害的。此外,正如您在評論中被告知的那樣,使用沒有虛函式的多型性(將指標轉換為基類)并沒有真正的意義。doubleDerived
長話短說,如果你有一個沒有虛函式的類層次結構,用戶會意識到這一點,并且永遠不會通過指向其基類的指標洗掉物件。因此,您沒有充分的理由將解構式設為虛擬或受保護。但是恕我直言,您至少應該在基類上留下評論,以警告未來的維護者可能存在的問題。
uj5u.com熱心網友回復:
如果沒有虛擬解構式,您對洗掉的呼叫可能是錯誤的。它應該是:
void do_something() {
Base* p = new Derived{1};
Derived *t = dynamic_cast<Derived*>(p);
if (t) {
delete t;
} else {
delete p;
}
}
您可以使用物件的向上/向下轉換將它們存盤在一個公共陣列或向量中,并且仍然能夠在沒有虛擬解構式的情況下呼叫派生物件的方法。這通常是糟糕設計的標志,但它是合法的 C 代碼。delete代價是你必須像上面那樣轉換回原始型別。
注意:dynamic_cast只有Base在至少有一個虛函式時才能完成。如果你有一個虛函式,你應該只添加虛解構式。
如果您不需要dynmaic_cast任何地方,那么請向我展示您不能使用陣列Base代替的情況Base *。
我猜想使基類的解構式受保護的目的是在有人洗掉 a 時產生錯誤,Base*這樣您就可以使解構式成為虛擬的。意味著在您真正需要它之前,您沒有虛擬解構式的開銷。
uj5u.com熱心網友回復:
fwiw 它正在發生,因為您嘗試通過Base. 如果您以某種方式真的想要僅具有基本型別的物件參考/指標,則有一些替代方法。
void do_something() {
Base&& b = Derived{1};
}
void do_something() {
Derived d{1};
Base* p = &d;
Base& b = d;
}
void do_something() {
std::shared_ptr<Base> sb = std::make_shared<Derived>(1);
}
// NOTE: `std::unique_ptr` doesn't work
void do_something() {
std::unique_ptr<Base> ub = std::make_unique<Derived>(1); // warning: this not work
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/482912.html
上一篇:如何在C 中定義編譯時三元文字?
下一篇:全域整數替代
