C++ is Virtual destructor still needed if there are no data members in derived?
Asked Answered
A

3

13

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?

Animatism answered 15/10, 2010 at 18:0 Comment(0)
H
7

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.

Haemocyte answered 15/10, 2010 at 18:8 Comment(5)
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.Expedition
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.Animatism
@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.Haemocyte
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.Shena
How is "technically undefined" different from "undefined"?Sandal
E
9

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.

Expedition answered 15/10, 2010 at 18:1 Comment(1)
+1 for "Anything could happen". Anything! Absolutely anything! :)Firstly
H
7

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.

Haemocyte answered 15/10, 2010 at 18:8 Comment(5)
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.Expedition
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.Animatism
@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.Haemocyte
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.Shena
How is "technically undefined" different from "undefined"?Sandal
B
2

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! 
}
Behave answered 15/10, 2010 at 19:15 Comment(1)
@Mike Ellery, yes that is what I wanted to meant. I have corrected the code.Behave

© 2022 - 2024 — McMap. All rights reserved.