0

I have two classes, while B derives A.

I created a pointer to A, is called: a2. please take a look in my main function.

What does this line do?

a2 = new B();

Why when I delete a2, only the destructor of A is activated?

#include <iostream>
using namespace std;

class A {
    int num;
  public:
    A() { cout << "constructor of A\n"; }
    void set_num(int new_num) { cout << "set_num of A" << endl; num = new_num; }
    void print() { cout << "print of A: ";  cout << num << endl; }
    ~A() { cout << "destructor of A\n"; }
};

class B: public A {
    int num;
  public:
    B() { cout << "constructor of B\n"; }
    void set_num(int new_num) { cout << "set_num of B" << endl; num = new_num; }
    void print() { cout << "print of B: ";  cout << num << endl; }
    ~B() { cout << "destructor of B\n"; }
};

void main() {
    A *a2;
    a2 = new B();
    delete a2;
}

this is the output:

constructor of A
constructor of B
destructor of A

Each help appreciated!

Alon Shmiel
  • 5,794
  • 18
  • 78
  • 126
  • If you change the type of `a2` from `A *` to `B *` (its **actual**, most specific type), then this works as you expected. Also, `main()` must return `int`, and **not** `void`. –  May 03 '13 at 22:01
  • @H2CO3, ok, thank you very much! – Alon Shmiel May 03 '13 at 22:03

3 Answers3

1

Make your destructors virtual first...

virtual ~A()... virtual ~B()...

look here: When to use virtual destructors?

Community
  • 1
  • 1
Mirco Ellmann
  • 943
  • 7
  • 8
1

If you are deleting an object through a pointer to a base sub-object, the destructor of the base class must be virtual:

class A
{
public:
    virtual ~A() { /* ... */ }
    // ...
};

(This will automatically make all the derived class destructors virtual as well, so you won't have to spell it out there.)

The reason is clause 5.3.5/3 from the C++11 standard:

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.

I'm sure you can imagine why the virtual destructor is, but for one simple example imagine that the pointer-to-base (like your a2) doesn't even have to be numerically the same as the pointer to the acutal object -- but you need the exact pointer to deallocate the memory. So clearly there is some magic needed along the way to figure out the correct address. The virtual destructor incorporates that magic.

Kerrek SB
  • 428,875
  • 83
  • 813
  • 1,025
1

So here the simplest and most convenient solution is to use virtual destructors, but let me show another solution as well: help the compiler. Type inference is useful here - if you declare the object to be of as specific type as possible, you'll get the expected behavior:

int main()
{
    B *a2;
    a2 = new B();
    delete a2;
}

outputs

constructor of A
constructor of B
destructor of B
destructor of A

Also, main() should return int, not void.