Question

I'm trying to understand destruction behaviour in C++ by following examples from: https://github.com/peterdemin/virtual-destruction-5-cents

Does that list fullfills every possible flow? What should be added? How given examples can be converted into short terms?

https://stackoverflow.com/a/461224/135079 comes up with "Always make base classes' destructors virtual when they're meant to be manipulated polymorphically." which doesn't cover Scenario 4.

Item 7 in Scott Meyers' Effective C++ states:

  • If a class has any virtual function, it should have a virtual destructor;
  • Classes not designed to be base classes or not designed to be used polymorphically should not declare virtual destructors.

which is light (should and should not) and confronts with Scenario 2.

UPDATE

I rewritten C++ standard provided by 6502 as pseudo-code:

if static type of object is different from its dynamic type:
    if the static type is a base class of the dynamic type:
        if the static type has a virtual destructor:
            We're fine - dynamic type's destructor will be called
        else:
            behavior is undefined [1]
    else:
        behavior is undefined [2]

[1] Code will compile without warnings and probably will work fine, but it's not guaranteed and may cause entangled error at runtime.

[2] That's awkward:

class A {};
class B {};
B *a = (B*)(new A());
delete a;
Was it helpful?

Solution

When you destroy a derived object using a base pointer and the destructor is not virtual you end up in an "undefined behaviour" scenario.

N3690, 5.3.5 [expr.delete] - 3

In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined

The explanation give in that github repository is just plain wrong ("the derived destructor is not called but no memory leak occurs"). You cannot count on that.

I didn't read the rest because it would be a waste of time. UB is UB... trying to describe the undefined is nonsense.

OTHER TIPS

When you declare the methods virtual, it means that you are instructing the compiler that it should always search for derived version of the method while working on derived class object. Its as simple as that.
In below example, if you do not use virtual keyword in base class method then base class version of method will be called.

#include <iostream>

class A
{
  public:
      virtual const char* fetchClassName() { return "A"; }
      // this is a virtual destructor:
      virtual ~A(){ cout<<"Destroying Base";}
  };

class B: public A
{
  public:
      virtual const char* fetchClassName() { return "B"; }
      virtual ~B(){ cout<<"Destroying Derive";}
};

int main(void)
{
   B obj_b;
   A &obj_a = obj_b;
   std::cout << obj_a.fetchClassName() << "\n";
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top