63

Can the default destructor be generated as a virtual destructor automatically?

If I define a base class but no default destructor, is there a default virtual destructor generated automatically?

lc.
  • 113,939
  • 20
  • 158
  • 187
  • 1
    by the way , just wondering , what is a default destrutor? is there more then one kind of destructor? – user88637 Jul 13 '09 at 05:51
  • 4
    @yossi1981: if you don't declare a destructor in a class, then the compiler inserts one for you. At risk of being wrong about some unusual case, this "default destructor" is the same as if you'd defined "~MyClass() {}". – Steve Jessop Jul 13 '09 at 10:22
  • 3
    @onebyone: to be precise: `public: ~MyClass() {}` - even though class members are by default private. – MSalters Jul 13 '09 at 10:30
  • 2
    A base class with a non-virtual destructor and a derived class with a virtual one feels like a built-in design flaw. – Spencer Mar 06 '18 at 11:04

8 Answers8

58

No. There is a cost associated with making a method virtual, and C++ has a philosophy of not making you pay for things that you don't explicitly state that you want to use. If a virtual destructor would have been generated automatically, you would have been paying the price automatically.

Why not just define an empty virtual destructor?

Uri
  • 88,451
  • 51
  • 221
  • 321
  • 71
    Note that you can also do `virtual ~Foo() = default;` as of [C++11](http://en.cppreference.com/w/cpp/language/member_functions#Special_member_functions) (if anyone is reading this as of recently) – Cory Kramer Feb 19 '15 at 19:02
  • 1
    What extra cost could there be, if the class has any other virtual functions at all? Could you give an example? – Spencer Jun 07 '16 at 14:13
  • 2
    @Spencer: Calling the destructor needs the address of the d-tor code to be resolved at runtime through the vtable of the object. For non-virtual destructors the adress of the code is known at compile time. – Marco Freudenberger Oct 17 '17 at 09:17
  • @Marco A base class with a virtual destructor and a derived class with a non-virtual one feels like a built-in design flaw. – Spencer Oct 17 '17 at 09:57
  • 1
    @Spencer: If the base class declares an (implicit or explicit) virtual destructor, the destructor of the derived class is implicitly declared virtual. If your base class has a non-virtual destructor it is dangerous to inherit from it and add new members because the destructor of these members is never called if you call delete with a pointer of the base class type! – Andreas H. Mar 06 '18 at 10:04
  • @Andreas This is all true, but Marco Freudenberger seemed to be implying otherwise. In 2016 when I first responded, I had read the question differently. Having assumed the base class destructor was virtual, I was trying to get Uri to explain his 2009 response. – Spencer Mar 06 '18 at 11:01
  • I wonder **if** the compiler will generate a virtual default destructor when another virtual function has been defined in the base class. I know that we should define it by hand if not. – Bryan YU Jun 19 '20 at 15:24
55

In C++ 11 you can use:

class MyClass
{
  // create a virtual, default destructor
  virtual ~MyClass() = default;
};
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • This compiles with ``icpc``, but not ``g++-4.6.3``, and gives the message ``error: ˜virtual MyClass::~MyClass() declared virtual cannot be defaulted in the class body``. Looks pretty explicit that they don't want you to do this; is there a version of ``g++`` that this works with? – user14717 Sep 02 '14 at 21:50
  • 1
    @NickThompson, I've used this with gcc 4.8.1 and 4.9.0 successfully. It [seems that this is supported in 4.6](https://gcc.gnu.org/gcc-4.6/cxx0x_status.html). Are you compiling with `-std=c++0x`? – Drew Noakes Sep 03 '14 at 08:36
  • I was; not sure what was happening there. – user14717 Sep 04 '14 at 23:20
  • 3
    Is there any difference in using `default` here compared to using an empty constructor with `{}` ? – Zitrax Jun 06 '17 at 09:43
  • 1
    @Zitrax I'm sure you meant _destructor_, not _constructor_. Notice that for constructor there _is_ a difference between an empty body user-provided constructor and the defaulted one (with = default). The difference is that the former prevents the class from being an aggregate class, while the latter doesn't. An aggregate class can be initialized with braces syntax, which sometimes can be useful/desired. Notice, however, that there are other details that can prevent a class from being an aggregate (most notably, virtual methods). – bartgol Mar 27 '19 at 22:19
  • 1
    Coming to think of it, there is a reason for using =default for the destructor, at least for the case where it is not virtual: it allows the class to be not only an aggregate, but a Plain Old Data (POD) struct (assuming the other requisites are satisfied). A user-provided empty destructor already prevents you from having a POD struct. – bartgol Mar 27 '19 at 22:22
11

Yes, by inheriting from a base class with a virtual destructor. In this case, you already pay the price for a polymorphic class (e.g. vtable).

MSalters
  • 173,980
  • 10
  • 155
  • 350
9

No, all destructor's are by default NOT virtual.

You will need to define a virtual destructor on all the base classes

In addition to that.

To quote Scott Meyers in his book "Effective C++":

The C++ language standard is unusually clear on this topic. When you try to delete a derived class object through a base class pointer and the base class has a non-virtual destructor (as EnemyTarget does), the results are undefined

In practice, it's usually a good idea to define a class with a virtual destructor if you think that someone might eventually create a derived class from it. I tend to just make all classes have virtual destructor's anyway. Yes, there is a cost associated with that, but the cost of not making it virtual more often that not out weighs a measly bit of run-time overhead.

I suggest, only make it non-virtual when you're absolutely certain that you want it that way rather than the rely on the default non-virtual that the compilers enforce. You may disagree, however (in summary) I recently had a horrid memory leak on some legacy code where all I did was add a std::vector into one of the classes that had existed for several years. It turns out that one of it's base classes didn't have a destructor defined (default destructor is empty, non-virtual!) and as no memory was being allocated like this before no memory leaked until that point. Many days of investigation and time wasted later...

hookenz
  • 36,432
  • 45
  • 177
  • 286
  • 1
    So if I understand the situation correctly, your code already had undefined behaviour (though not a memory leak) before you made the change: being deleted via a base class pointer, your derived object gets is base destructed without (first) being destructed itself. The absence of other data members (that would need destruction) does not make the behaviour defined. So your investigation was not wasted effort... – Marc van Leeuwen Jul 23 '14 at 12:15
8

Uri and Michael are right -- I'll just add that if what's bugging you is having to touch two files to declare and define the destructor, it's perfectly all right to define a minimal one inline in the header:

class MyClass
{
   // define basic destructor right here
   virtual ~MyClass(){}

   // but these functions can be defined in a different file
   void FuncA();
   int FuncB(int etc);
}
Crashworks
  • 40,496
  • 12
  • 101
  • 170
  • Actually I think you'll find that when you link this, you'll get an undefined reference to MyClass' vtable. – keraba Jul 13 '09 at 03:11
  • 2
    You'll only get an "undefined reference to vtable" error if you're using GCC and you don't define FuncA and FuncB non-inline, and that's only because GCC has failed to emit all the necessary stuff to allow for proper linking. – Rob Kennedy Jul 13 '09 at 05:05
  • I'm surprised by this, why would this cause a linking problem? Can someone elaborate? – Uri Jul 13 '09 at 05:16
  • 3
    I do it all the time and it links just fine in MSVC, not to mention that the C++ standard explicitly allows for this. I guess it's a bug in GCC. – Crashworks Jul 13 '09 at 05:23
2

Currently, Uri is right. On the other hand, after you have declared a virtual method in your class, you are paying the price for the existence of the virtual table anyway. In fact, the compiler will warn you if your class has a virtual method, but no virtual destructor. This could become a candidate for automatic generation of the default virtual destructor instead of the pesky warning.

Thinkeye
  • 655
  • 6
  • 6
1

No. You need to declare it as virtual.

Michael Aaron Safyan
  • 93,612
  • 16
  • 138
  • 200
0

Some people stated that it is never defaulted to virtual. That's not exactly true.

Even though destructors are not inherited, if a base class declares its destructor virtual, the derived destructor always overrides it.

This means that if the base class has a virtual destructor you don't have to define a destructor of the derived class as virtual nor explicitly write:

/// All of these are unnecessary and won't change the destruction behavior
/// as long as Class inherits from a base class with a virtual destructor
virtual ~Class() = default;
// or
~Class() override = default;
// or
~Class() {}