0

Lets take this example:

    /* Source.cpp */

    struct Base {
        virtual void func() = 0;
    };

    struct Derived : public Base {
        virtual void func() override { }
    };

    int main() {
        return 0;
    }

Upon compilation (on g++ 8.3.0) via g++ Source.cpp -Wnon-virtual-dtor we get this:

    Source.cpp:2:8: warning: 'struct Base' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
     struct Base {
            ^~~~
    Source.cpp:6:8: warning: base class 'struct Base' has accessible non-virtual destructor [-Wnon-virtual-dtor]
     struct Derived : public Base {
            ^~~~~~~
    Source.cpp:6:8: warning: 'struct Derived' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]


What is the practical thing to do?

  • Add virtual ~Base() = default; to every such class Base to get rid of the warning (downside is we are adding boilerplate code, which inherently doesn't seem to do anything).
  • Or is there an argument to remove -Wnon-virtual-dtor and leave the code untouched? (downside is we are potentially allowing memory leaks, or are we)
  • I guess a question worth asking is, why doesn't the compiler create a virtual default destructor if the class has virtual members?
Phil-ZXX
  • 2,359
  • 2
  • 28
  • 40
  • @VTT: My question is about the implications of boilerplate code, and whether or not, one should add it. I am **not** asking "in which instance do we need to make destructors virtual". – Phil-ZXX May 22 '19 at 13:22
  • 2
    To which part of this code you are referring to as "boilerplate"? Virtual destructor in base class is not a boilerplate because it is a necessary code that makes it possible to hold ownership of derived object through a pointer to a base object. You don't add it to get rid of the warning, you add it when you want to make that particular ownership pattern work. – user7860670 May 22 '19 at 13:35
  • 2
    Adding a virtual destructor is not boilerplate. It allows you to create a derived class and then delete it through a pointer to the base class. Without the virtual destructor only the base class allocaed memory would be freed, not the whole base+derived class allocated memory. The compiler does not create a virtual default destructor because maybe you don't want it. Maybe you won't delete through pointers to base. It does not know what you want to do with the class. – mcabreb May 22 '19 at 14:11
  • 1
    It's *possible* to have virtual methods and a nonvirtual destructor, and not have undefined behaviour, so long as you never delete `Base *`s. That's why it's a warning and not an error – Caleth May 22 '19 at 14:27
  • Remember that compilers can and will optimize, and even inline a call to a virtual function or destructor when possible. – Michaël Roy May 22 '19 at 14:27
  • @mcabreb -- without the virtual destructor, the behavior (when deleting an object of a derived type through a pointer to base) is undefined. What you describe is a possible consequence, but it is not required and not usually what happens. – Pete Becker May 22 '19 at 15:49

0 Answers0