[英]Do I need a virtual destructor for a second interface class?
I've got classes called "Base" and "Derived".我有名为“Base”和“Derived”的课程。
struct Base {
Base() = default;
virtual ~Base() = default;
Base(const Base&) = delete;
Base& operator=(const Base&) = delete;
virtual void DoStuff() = 0;
};
The "Base" class needs virtual destructor and it's understandable. “基地” class 需要虚拟析构函数,这是可以理解的。 Also I don't allow copying of this 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;
}
Now let's introduce other classes called, I don't know, Callable
and DerivedCallable
现在让我们介绍其他的类,我不知道,
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
does not inherit from Callable
, so callableA
is nullptr, thus the if statement won't execute the Call()
function. Derived
不继承自Callable
,因此callableA
为 nullptr,因此 if 语句不会执行Call()
function。
DerivedCallable
on the other hand inherits from Callable
and the std::dynamic_pointer_cast
will increase the ref count of the object to 2, so when the callableB
gets out of the scope the object won't be deallocated, only the refcount will decrease to 1 and then the main function will deallocate b
.另一方面,
DerivedCallable
继承自Callable
, std::dynamic_pointer_cast
会将 object 的引用计数增加到 2,因此当callableB
离开 scope 时,object 不会被释放,只有引用计数会减少到 1 并且然后主 function 将释放b
。
Does Callable
need to have a virtual destructor? Callable
是否需要有一个虚拟析构函数?
You only need a virtual destructor if you are ever going to delete a derived class object through a base class pointer.如果您要通过基指针 class 删除派生的 class object,则只需要一个虚拟析构函数。
Since you are using std::shared_ptr
, you don't need any virtual destructors because the shared_ptr stores a correctly typed deleter (no matter how you cast it).由于您使用的是
std::shared_ptr
,因此不需要任何虚拟析构函数,因为 shared_ptr 存储了正确类型的删除器(无论您如何转换)。
If you are ever going to own a DerivedCallable
object with a Callable
pointer ( std::unique_ptr<Callable>
or something else that calls delete
on a Callable*
), then it should have a virtual destructor.如果您打算拥有一个
DerivedCallable
object 和一个Callable
指针( std::unique_ptr<Callable>
或其他在Callable*
上调用delete
的东西),那么它应该有一个虚拟析构函数。 However, if you only ever have non-owning references with Callable*
, then you don't strictly need the virtual destructor.但是,如果您只对
Callable*
进行非拥有引用,那么您并不严格需要虚拟析构函数。
Adding a virtual destructor when the class already has other virtual members is very cheap, so it's fine to add it so that you don't have to worry about accidentally delete
-ing it wrong.在 class 已经有其他虚拟成员的情况下添加一个虚拟析构函数是非常便宜的,所以添加它就可以了,这样你就不用担心不小心
delete
-ing 错误了。
It depends.这取决于。 In theory,
Base
doesn't need a virtual destructor.理论上,
Base
不需要虚拟析构函数。 You need a destructor to be virtual when you lug around an object which has a different dynamic type than its static type.当你拖着 object 时,你需要一个析构函数是虚拟的,它的动态类型与其 static 类型不同。
In your example, you have Base
pointer that really points to a Derivied
object. If you were not to make ~Base()
virtual, then, destroying that object would exhibit undefined behaviour -- likely by failing to destroy the Derived
portion of the object.在你的例子中,你有一个真正指向
Derivied
的Base
指针。如果你不使~Base()
虚拟化,那么破坏 object 将表现出未定义的行为——可能是因为未能破坏 object 的Derived
部分.
So, as long as you don't plan to have an (owning,) pointer to your object through a particular base class. that base class's destructor need not be virtual.因此,只要您不打算通过特定基类 class 拥有指向您的 object 的(拥有的)指针。该基类的析构函数不必是虚拟的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.