7

I am a newbie and I know this is a very basic concept and might be a duplicate too. Is it not true that once a constructor is called its corresponding destructor has to be called? [code run on Dev C++]

class Base
    {
     public:
            Base() { cout<<"Base Constructor\n";}
            int b;
     ~Base() {cout << "Base Destructor\n"; }
    };

class Derived:public Base
{
 public:
        Derived() { cout<<"Derived Constructor\n";}
        int a;
 ~Derived() { cout<< "Derived Destructor\n"; }
}; 
int main () {
Base* b = new Derived;    
//Derived *b = new Derived;
 delete b;
    getch();
    return 0;
}

GIVES OUTPUT

Base Constructor
Derived Constructor
Base Destructor
Raghu
  • 244
  • 2
  • 10
  • not sure if it is the problem, but have you tested using virtual destructors? – MariusSiuram Aug 09 '14 at 15:43
  • You usually want to declare the destructor of the base class a `virtual` method, otherwisewhen you delete the instance of the `Derived` object using a `Base *` pointer, `~Derived()` wont be called. – jotik Aug 09 '14 at 15:46

2 Answers2

14

Your code has undefined behavior. The base class's destructor must be virtual for the following to have defined behavior.

Base* b = new Derived;    
delete b;

From the C++ standard:

5.3.5 Delete

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

So in your case, the static type is Base, and the dynamic type is Derived. So the Base's destructor should be:

virtual ~Base() {cout << "Base Destructor\n"; }
PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
  • 2
    Here's a good online reference that details this behavior: http://en.cppreference.com/w/cpp/language/delete. Here's the relevant section: *"If expression evaluates to a pointer to the base class subobject of the object that was allocated with new, the destructor of the base class must be virtual, otherwise the behavior is undefined."* – Michael Kelley Jan 18 '16 at 19:09
4

There is no need to call a destructor if it is trivial.

That does not help in your example though, because if a class has a sub-object with non-trivial destructor (member or base) or its own destructor is user-defined, it is not trivial.

Also, you may only delete a class using a pointer to base, if that base-class has a virtual destructor, on pain of undefined behavior (The compiler need not warn you).

Pro-tip: If you need to make it virtual (for example due to above requirement), but do not want to prevent it from being trivial (some containers and algorithms have optimized implementations for trivial types), use:

virtual ~MyClass = default; // Since C++11

So, never delete using a pointer to Base if Base does not have a virtual destructor or it is actually really a base.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • If the destructor is trivial, why does it need to be virtual? – Neil Kirk Aug 09 '14 at 15:56
  • 1
    As said, because you might want to delete a `Derived` using a `Base*`. – Deduplicator Aug 09 '14 at 15:58
  • But if the destructor is trivial, what in Derived needs to be deleted? – Neil Kirk Aug 09 '14 at 16:58
  • @NeilKirk: The `delete` expression does not only need to invoke the right destructor, but also needs to pass the right pointer and size to the right operator delete. Anyway, that's the reason why deleting through a base pointer if the base does not have a virtual destructor is UB. – Deduplicator Aug 09 '14 at 17:34