views:

119

answers:

3

Suppose I have this code

class Base{
  public:
        int getVal();
  private:
         int a, b;
};

class Derived::public Base{
    public:
         void printVal();
};

int main(){
    Base *b = new Derived();
    delete b;    
}

I know a virtual destructor would delete things properly, but is it bad to delete with base pointer (when there is no virtual destructor) even if there are no virtual functions and no data members in the derived class? What will happen if this is done?

+6  A: 

Is it bad to delete with base pointer (when there is no virtual destructor) even if there are no virtual functions and no data members in the derived class?

Yes.

The behavior is undefined regardless the contents of the derived class.

What will happen if this is done?

Anything could happen.

James McNellis
Thank you very much James.
snk
+1 for "Anything could happen". Anything! Absolutely anything! :)
ybungalobill
+3  A: 

For primitive-type data, your example will most likely work in practice. As a matter of fact, incurring a vtable could actually hinder performance (so there may be some legitimate use here), but it is technically undefined, per 5.3-5.4:

If the static type of the operand [of the delete operator] 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 behaviour is undefined.

It really all depends on the "heapness" of the data in your class, and as there are no heap-allocated members (in your case), you should be fine, but it's definitely a code smell.

David Titarenco
Thank you David.
snk
It's dangerous to rely on things that will "most likely work" and assume that you "should be fine." It's far better to write code that _will_ work, then you _know_ you'll be fine.
James McNellis
James, I will make sure that there is always a virtual destructor. This is just a hypothetical asked by someone and did not have an answer for it. Thank you both again.
snk
@James, I actually think that this *might* work every time with primitives (just because of how objects are allocated/deallocated in C++), and the clause is added as a generality since more often than not, some members will be heap allocated.
David Titarenco
It's also worth thinking about what would happen if someone later derives a new class from Derived, and that class *does* have members that need to be destroyed. If your base does not have a virtual destructor then the new class cannot safely be used polymorphically.
dajames
+2  A: 

The virtual desctructor in the derived class is needed in order to properly call the derived destructor (polymorphism), when the derived object is created through a pointer to the base class.

High Integrity CPP Rule 3.3.2 Write a 'virtual' destructor for base classes. (QACPP 2116)

Justification: If an object will ever be destroyed through a pointer to its base class, then that base class should have a virtual destructor. If the base class destructor is not virtual, only the destructor for the base class will be invoked. In most cases, destructors should be virtual, because maintenance or reuse may add derived classes that require a virtual destructor.

class Base {}; 
class Derived : public Base { public: ~Derived() {} }; 

void foo() {  
   Derived* d = new Derived; delete d; // correctly calls derived destructor 
} 
void boo() { 
   Derived* d = new Derived; Base* b = d; delete b; // problem! does not call derived destructor! 
}
ArceBrito
I think you meant your destructor to be named `~Derived`, not `~C`...
Mike Ellery
@Mike Ellery, yes that is what I wanted to meant. I have corrected the code.
ArceBrito