![](/img/trans.png)
[英]Do I need to define a virtual destructor even if the base and derived class only use primitive data types?
[英]Do I need a virtual destructor for a second interface class?
我有名為“Base”和“Derived”的課程。
struct Base {
Base() = default;
virtual ~Base() = default;
Base(const Base&) = delete;
Base& operator=(const Base&) = delete;
virtual void DoStuff() = 0;
};
“基地” class 需要虛擬析構函數,這是可以理解的。 我也不允許復制這個 class
struct Derived : Base {
Derived() = default;
~Derived() override = default;
void DoStuff() override { /*...*/ }
};
int main()
{
std::shared_ptr<Base> a = std::make_shared<Derived>();
a->DoStuff();
return 0;
}
現在讓我們介紹其他的類,我不知道, Callable
和DerivedCallable
struct Callable
{
virtual void Call() = 0;
};
struct DerivedCallable : Base, Callable
{
DerivedCallable() = default;
~DerivedCallable() override = default;
void DoStuff() override { /*...*/ }
void Call() override { /*...*/ }
};
int main()
{
std::shared_ptr<Base> a = std::make_shared<Derived>();
a->DoStuff();
{
auto callableA = std::dynamic_pointer_cast<DerivedCallable>(a);
if(callableA) {
callableA->Call();
}
}
std::shared_ptr<Base> b = std::make_shared<DerivedCallable>();
b->DoStuff();
{
auto callableB = std::dynamic_pointer_cast<DerivedCallable>(b);
if(callableB) {
callableB->Call();
}
}
return 0;
}
Derived
不繼承自Callable
,因此callableA
為 nullptr,因此 if 語句不會執行Call()
function。
另一方面, DerivedCallable
繼承自Callable
, std::dynamic_pointer_cast
會將 object 的引用計數增加到 2,因此當callableB
離開 scope 時,object 不會被釋放,只有引用計數會減少到 1 並且然后主 function 將釋放b
。
Callable
是否需要有一個虛擬析構函數?
如果您要通過基指針 class 刪除派生的 class object,則只需要一個虛擬析構函數。
由於您使用的是std::shared_ptr
,因此不需要任何虛擬析構函數,因為 shared_ptr 存儲了正確類型的刪除器(無論您如何轉換)。
如果您打算擁有一個DerivedCallable
object 和一個Callable
指針( std::unique_ptr<Callable>
或其他在Callable*
上調用delete
的東西),那么它應該有一個虛擬析構函數。 但是,如果您只對Callable*
進行非擁有引用,那么您並不嚴格需要虛擬析構函數。
在 class 已經有其他虛擬成員的情況下添加一個虛擬析構函數是非常便宜的,所以添加它就可以了,這樣你就不用擔心不小心delete
-ing 錯誤了。
這取決於。 理論上, Base
不需要虛擬析構函數。 當你拖着 object 時,你需要一個析構函數是虛擬的,它的動態類型與其 static 類型不同。
在你的例子中,你有一個真正指向Derivied
的Base
指針。如果你不使~Base()
虛擬化,那么破壞 object 將表現出未定義的行為——可能是因為未能破壞 object 的Derived
部分.
因此,只要您不打算通過特定基類 class 擁有指向您的 object 的(擁有的)指針。該基類的析構函數不必是虛擬的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.