0

I have a few classes (around 10 in my project) that needs a virtual destructor while also requiring support for std:move and std::copy calls. To keep both copy and move semantics in these classes, I added another class to serve as a base class for these classes:

/*
This class should be inherited by any class that:
- needs a virtual destructor,
- doesn't require explicit definitions of destructor, copy/move constructor/assignment
- needs to support copy and move semantics.

Such classes can inherit from the class defined below to make their destructor virtual,
and keeping copy and move semantics intact.

INFO: This class won't be able to serve it's purpose if any of the 5 mentioned member
functions are explicitly defined in the derived class.
*/

class VirtualDtor
{
protected:
   virtual ~VirtualDtor() = default;
};

This class drew some concerns such as - A derived class may (by mistake or design) explicitly define one or few of the 5 member functions, even after inheriting from VirtualDtor. That would lead to the removal of copy/move semantics defeating the purpose of VirtualDtor. To avoid such scenarios, maintaining rule of 5 by declaring the 5 functions as default in each class individually could bring some clarity about what to expect.

But inheriting from this class will make the code more readable and if we understand it's requirements and usage before inheriting, it will not cause any unexpected behavior.

So I would like to know which is a better way of handling virtual destructors and the rule of 5.

Note: I could have added copy and move member functions too in the VirtualDtor class like it's suggested here. I didn't keep them to avoid the mistaken impression that any class that derives from VirtualDtor will inherit copy and move-semantics which it won't. It will only make the destructor in derived classes virtual. So I skipped the rule of 5 in VirtualDtor.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
AMaz
  • 13
  • 2
  • 3
    Honestly, i don't think inherting from a base class like VirtualDtor is more readable than just implementing a virtual destructor in the classes that need one. – Eric Nov 27 '19 at 11:50
  • 2
    You may wish to consider following - and requiring derived classes to follow - the rule of zero rather than rule of five. The default is then easy - derived classes don't need to implement any of the five and, if a developer chooses to implement any of the five, the onus is on them to justify a claim that their class works as intended. I personally would not bother with having a base class with the only purpose of providing a virtual destructor - a base class should provide some facilities (e.g. interface) that are needed by the derived classes. – Peter Nov 27 '19 at 12:21

1 Answers1

2

Adding a base class such as VirtualDtor can't enforce anything on the derived classes.

The best way to enforce rule of 5 is through a style checker such as clang-tidy, which has an option for this sort of thing: https://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-special-member-functions.html

Anthony Williams
  • 66,628
  • 14
  • 133
  • 155
  • Thanks for the `clang-tidy` insight, it's quite helpful. I am guessing that you're suggesting to use it to flag classes that don't follow rule of 5, so that we add missing member functions inside the class. Let me know if I am wrong. My motivation to `VirtualDtor` is to use Rule of 0 (less error-prone) while having a virtual destructor. [Here](https://godbolt.org/z/pHWBK5), I have intentionally skipped on adding the virtual destructor (common mistake), creates warning. [Here](https://godbolt.org/z/SvgmQk), I have added `VirtualDtor`. I've checked if rule of 5 is enforced. It works alright. – AMaz Nov 28 '19 at 07:09
  • Yes, I was suggesting that you use clang-tidy to flag classes that don't follow the rule of 5. Your `meets_rule_of_5` check doesn't actually check that, it just checks that the type can be moved and copied, not that they do something sensible. If you provide a copy constructor or just a copy assignment operator, then your type will still pass the check. https://godbolt.org/z/wAD247 – Anthony Williams Nov 28 '19 at 08:40