1

Is it ok to delete an abstract class instead of a child? Will all allocs be deallocated thereby?

Consider a following situation as an example, but please do not limit your answers to that one case:

struct A {
    virtual void fun() = 0;
};
struct B : public A {
    void fun() { /* actually doing something here. */ }
};
struct C {
    A *a;
    void OneTask() {
        // (...)
        a = new B();
    }
    void AnotherTask() { /* using fun() in some way. */ }
    ~C() { delete a; }
};

The idea is to have multiple possible outcomes of OneTask() which result in an assignment of a pointer to different classes that inherit from A, B being just an example; and then to use such result reasonably in AnotherTask() and other methods of class C.

yauser
  • 667
  • 2
  • 8
  • 17
  • 1
    You should read about [When to use virtual destructors](http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors). – Joe Apr 10 '13 at 20:03
  • @Dariusz In order to spare my time and lines writing "public:" – yauser Apr 10 '13 at 20:05
  • @yauser Do you understand the importance of OOP? Or I should say risk of not using encapsulation? – Joe Apr 10 '13 at 20:06
  • @Joe of course I do but do you *really* think that I should use encapsulation in the purposefully simplified example I provided? – yauser Apr 10 '13 at 20:09
  • Fair enough, the less code the better for posting here. We were just looking out for you. – Joe Apr 10 '13 at 20:12
  • @Joe True, thank you, that would be indeed alarming if someone would consider actually coding in that manner ;) – yauser Apr 10 '13 at 20:17

3 Answers3

2

You must have virtual destructor in base class else complete destruction of derived class doesn't happen.

struct A {
    virtual void fun() = 0;
virtual ~A()
   {
    }
};
shivakumar
  • 2,934
  • 15
  • 28
  • I understand and will bear that in my heart, but would the complete destruction really fail even for my trivial example? – yauser Apr 10 '13 at 20:14
  • yes it will fail. You can verify by defining destructor and putting "cout" message. you can observe that derived class destructor is not called. – shivakumar Apr 10 '13 at 20:21
  • Formally, the behavior is undefined if you delete an object of a derived type through a pointer to a base that does not have a virtual destructor. – Pete Becker Apr 10 '13 at 20:34
  • And often that means calling the _least_ derived dtor which is still implemented (in optimized builds), because that's the last one which could legally be called. That's why @shivakumar's test is troublesome: the result depends on optimizer behavior, and it will assume no Undefined Behavior. – MSalters Apr 11 '13 at 08:14
1

Yes, it's perfectly fine to delete a without knowing what actual derived type a is pointing to.

As shivakumar pointed out, if you don't make your base class's destructor virtual, then deleting a derived class will not end up calling the base class's destructor. In your trivial example that's not a problem, but in real life you should always make your destructors virtual.

Nate Hekman
  • 6,121
  • 24
  • 30
0

If A has a virtual destructor then both destructors of A and B are succesfully called (first B then A) ,

If you do not declare the constructor of A as virtual, then only the destructor of A is called during deletion and extended data of B may leak.

struct A {
   virtual void fun() = 0;
   virtual ~A();
};
struct B : public A {
   void fun() { /* actually doing something here. */ }
   ~B();
};
fatihk
  • 7,509
  • 22
  • 44
  • But if I do not add any further fields in children classes, only new methods, then no leaks are possible, right? – yauser Apr 11 '13 at 22:39
  • @yauser Yes, that is right, but also you can not use the destructor of B for any purpose like terminating some operation. – fatihk Apr 12 '13 at 04:43