What if the virtual destructor defined in derived class, but not the top of hierarchy? C++

戏子无情 提交于 2020-01-30 12:25:12

问题


I wonder is it correct to define a base class with no virtual destructor, and define inherited classes with the virtual one? What would actually happen if I do that?


回答1:


If you delete p where p is of type X* but actually points to a Y which is derived from X, you have undefined behavior unless X has a virtual destructor. If Y's destructor is virtual but Xs destructor is not it changes exactly nothing.




回答2:


If you intend to do

delete pB;

where pB is of type Base* and pB might point to an object of type Derived, where Derived is a (direct or indirect) derived class of Base, then,

you must declare a virtual destructor for Base.

So long as you don't intend to do this, it is fine for Base to not have a virtual destructor.

In particular, if you have class B1 with a non-virtual destructor, and a class B2 that derives from B1 with a virtual destructor, and a class D that derives from B2, it is fine to use a pointer to B2 to delete an object of type D, since B2 has a virtual destructor... but it would be undefined behaviour to use a pointer to B1 to delete an object of type B2 or D, since B1 does not have a virtual destructor.

In any case, the idea of a function being virtual in a derived class and non-virtual in a base class is confusing, so I would not do it unless I had a very good reason.




回答3:


A virtual destructor allows you to invoke the correct destructor with just a pointer to the baseclass. Without the virtual destructor, delete base_ptr will only invoke the base-class' destructor (or invoke undefined behaviour). However, whether the destructor call is dispatched dynamically depends only on the base class, so if the baseclass doesn't make it virtual, this will not suddenly become a virtual dispatch if some derived class adds a virtual destructor!

Notes:

  • If the baseclass doesn't have a virtual destructor, don't use it as a baseclass. At most, use private/protected inheritance, but not public inheritance.
  • If you write the baseclass but don't want to require a virtual destructor (common when writing mixins), you can make the destructor protected instead.

These two advises prevent accidental calls to the non-virtual baseclass destructor.




回答4:


It won't work if you don't declared virtual in parent class.

[~/cpp/VirtualDestructor]$ cat main.cpp
class A
{
public:
    ~A() {}
};

class B : public A
{
public:
    B() : val(new char) {}
    virtual ~B() { delete val; }
private:
    char* val;
};

int main()
{
    A* x = new B;
    delete x;
}
[~/cpp/VirtualDestructor]$ valgrind ./run 
==20382== Memcheck, a memory error detector
==20382== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==20382== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==20382== Command: ./run
==20382== 
==20382== 
==20382== HEAP SUMMARY:
==20382==     in use at exit: 1 bytes in 1 blocks
==20382==   total heap usage: 2 allocs, 1 frees, 17 bytes allocated
==20382== 
==20382== LEAK SUMMARY:
==20382==    definitely lost: 1 bytes in 1 blocks
==20382==    indirectly lost: 0 bytes in 0 blocks
==20382==      possibly lost: 0 bytes in 0 blocks
==20382==    still reachable: 0 bytes in 0 blocks
==20382==         suppressed: 0 bytes in 0 blocks
==20382== Rerun with --leak-check=full to see details of leaked memory
==20382== 
==20382== For counts of detected and suppressed errors, rerun with: -v
==20382== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
[~/cpp/VirtualDestructor]$

B instance is pointed by a A* pointer. Then when you delete it. It will go through the destructor of A if A's destructor is not virtual



来源:https://stackoverflow.com/questions/27534500/what-if-the-virtual-destructor-defined-in-derived-class-but-not-the-top-of-hier

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!