0
votes

This question looks like the discussion in Virtual destructor: is it required when not dynamically allocated memory?

In an exam question, I have been asked: - What should any base class that maintain pointers to dynamically allocated memory define?

I answered: - A copy constructor and an assignment operator (to make sure NOT only pointers are copied... c.f. deep copy), and a destructor (to free allocated memory)

They said this is not correct because this base class should also define a virtual destructor instead of the plain destructor. Why?

6
You should ask your examiner, not us. She is the one who asserts that you that you need a virtual destructor. - Robᵩ
You are perfectly entitled to an explanation from your examiner as to why and this should be your first action. - mathematician1975
The bit about containing dynamically allocated resources is a bit of a red herring. The key thing is "base class", which implies inheritance, and hence the possibility for deleting a derived class via a base-class type pointer which is where you need to worry about virtual destructors. - Rook

6 Answers

6
votes

If your class is intended to be used polymorphically, you'll likely have pointers to the base class that point to derived objects.

Deleting a derived object through a pointer to a base class with no virtual destructor causes undefined behavior. That's probably her reasoning.

5.3.5

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. [...]

5
votes

Your base class needs a virtual destructor if objects of derived classes are intended to be destroyed via a base-class pointer, like so

Base *pointer_to_base_class = new Derived;
delete pointer_to_base_class;

From your question, it is unclear whether this is the case. Perhaps another part of the question (or a previous question) made clear that such polymorphic destruction was intended. Or, perhaps you were taught during the class to always anticipate such use as a best practice.

5
votes

They are not 100% correct. Virtual destructor is a must if

  1. class hierarchy used with dynamic polymorphism AND
  2. derived objects are destroyed via pointer to base.

Otherwise non-virtual destructor is OK. But in most cases even if only #1 is intended it's a good style to make destructor virtual regardless of #2.

1
votes

Within the standard, most inheritance hierarchies have a virtual destructor at their base; however, sub_match is defined to public inherit from std::pair<BidirectionalIterator, BidirectionalIterator> and as such it could own dynamically allocated memory. In a related area, match_results is not required to but usually implemented to public inherit from std::vector<...> which definitely allocates memory.

Your examiner is not entirely incorrect, but the focus on dynamically allocated memory is a red herring and betrays a worrying ignorance of the standard; while in most implementations deleting a derived type by a pointer to base type without virtual destructor will result in destructing a sliced object, per the standard it is undefined behaviour.

0
votes

Adding to the other answers: You could also envisage a situation where you do want a common base class, but you don't have any actual interface functions for it. But if you want RTTI and dynamic cast support, you need a virtual function in your class. A destructor can be just that function.

For example, imagine you're a recovering Java programmer and insist that everything is an Object. You might start your first C++ program like so:

class Object
{
public:
   virtual ~Object() { }
};

Now Object can indeed serve as the ultimate polymorphic base class of each of your classes.

If you also think that Object should be abstract, you can even make the destructor pure-virtual:

class Object { public: virtual ~Object() = 0; }; Object::~Object() { }

0
votes

To follow up with all good answers here this is good practice to declare a virtual destructor to ensure a proper clean-up when a class is supposed to be subclassed to form a hierarchy and you want to delete the derived object through a pointer to it. The C++ standard is clear on this:

when you want to delete a derived class object through a base class pointer and the destructor of the base class is not virtual and the result is undefined

By undefined behavior you could think of memory leaks for example if your derived class allocate some dynamic memories and you try to delete it later on through this base class. Your teacher was probably thinking of this scenario.