4

Possible Duplicate:
When to use virtual destructors?

If all the data members of a class (which has virtual function) and it's inherited class are of non pointer type (means it can not hold any dynamic memoroy), is it required to declare destructor as virtual?

Example

class base {
    int x;
public:
    virtual void fn(){}

};

class der: public base {
    int y;
public:
    void fn(){}

};

Here do we need a virtual destructor?

Community
  • 1
  • 1
user966379
  • 2,823
  • 3
  • 24
  • 30

4 Answers4

6

No, it's not always necessary. It's just a rule of thumb, and thus not always applicable.

The real rules says:

A destructor must be declared virtual when objects of derived classes are to be deleted through base class pointers.

Otherwise, deleting a derived class object through a base class pointer invokes undefined behavior. (The most likely outcome is that only the base class' destructor is called.)

Of course, that rule is quite a mouthful for newbies, hence the simpler rule of thumb, which is almost always right. It is very likely that you are managing dynamically created derived class objects through base class pointers in a polymorphic class hierarchy, and it is very unlikely that you do this for non-polymorphic class hierarchies.

sbi
  • 219,715
  • 46
  • 258
  • 445
3

A virtual destructor ensures that the inherited class destructor is called when you have a pointer to a base class.

In this particular case you don't need it, but a user could inherite from der another class (let it be foo) which uses -for example- dynamic memory allocation. In that case the destructor wouldn't be called unless he has a pointer of type foo.

So no, it's not "necessary" but if you already have at least a virtual function (hence you already have a VTABLE) there is no harm either. It's mandatory if you assume that those class are to be inherited by the user and are freed using a pointer to the base class.

Emiliano
  • 22,232
  • 11
  • 45
  • 59
2

No, it is not required and doing so at all times can even hurt performance.

You don't run into UB (undefined behavior) unless you delete a base class pointer actually storing a derived class object. So whether you need a virtual destructor depend on how your code actually creates and frees objects, not on the class alone.

Btw it doesn't matter whether a derived class requires any extra destruction compared to a base class - lacking a virtual destructor in case when delete is applied to a base class pointer storing a derived class object address is UB anyway.

Chris Nolet
  • 8,714
  • 7
  • 67
  • 92
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • With regard to performance: it should not really matter as long as you inline the destructor body. – Matthieu M. Feb 01 '12 at 12:18
  • 1
    @Matthieu M.: A virtual destructor is usually called using vtable - such calls are not inlined. – sharptooth Feb 01 '12 at 12:22
  • Hurt performance? How? The cost of the vtable is already paid for (the assumption in the question is that there is at least one other virtual function). Now if the objects are destroyed through pointers to base, it is a requirement, if they have auto storage the call will be statically dispatched. Only if they are `deleted` through a pointer to the complete object the cost of the dynamic dispatch is hit, and even then it is negligible. This kind of misleading comments about performance is what makes new programmers do things *wrong* to avoid costs that are not there. – David Rodríguez - dribeas Feb 01 '12 at 12:25
  • @sharptooth: Actually no. A `virtual` destructor is called using a vtable if two conditions are met: the invocation does not precise which static type should be used *and* this static type cannot be inferred. If the static type is known, then the call can be inlined. This is important for destructors to be able to inline them because child classes invoke the base class destructor statically. – Matthieu M. Feb 01 '12 at 12:26
  • Note: I assume UB means Undefined Behaviour, although I've never seen it referred to as such before. – Peter Wood Feb 01 '12 at 12:29
  • @PeterWood UB is used as a shorthand for undefined behavior here quite often, in many cases in comments where the character count might be a limiting factor. – David Rodríguez - dribeas Feb 01 '12 at 12:36
  • @ David Rodríguez - dribeas: I even have an example of extra code generated for virtual destructor http://stackoverflow.com/q/8052146/57428 I've done my homework before writing this answer and I said *can hurt*, not *will hurt*. – sharptooth Feb 01 '12 at 12:42
  • @Matthieu M.: It *can* be inlined, but it doesn't mean it will be. Visual C++ 10 can't do any such deduction. – sharptooth Feb 01 '12 at 12:43
  • @MatthieuM. Also note that the cases where the call will be dynamic can be divided in two categories: when the static type of the pointer *is not* the type of the actual object, in which case the discussion is not about performance, but correctness (a non virtual destructor is UB) and the cases where the types are the same, which is the only case in which there is a *negligible* cost (the extra indirection *per object* will not make a dent in run time) – David Rodríguez - dribeas Feb 01 '12 at 12:45
  • @sharptooth the linked question is not related to whether the destructor is virtual or not, but on the contrary to whether the destructor was called by `delete` I.e. needs to deal locate the memory. Many compilers will generate 3 constructors per constructor in C++, and two destructors *always* regardless to whether the destructor is virtual or not. Play a bit with that example, make the destructor non virtual, try with objects with auto storage... The only *extra* cost would be the indication throught the vtable and only in the few cases where that is not required for correctness. – David Rodríguez - dribeas Feb 01 '12 at 12:51
  • @DavidRodríguez-dribeas: actually, the virtual call itself is not much of an issue, compared to a regular call. What can really hurt performance is that if the static call is not deduced, then it cannot be inlined. – Matthieu M. Feb 01 '12 at 12:51
  • @sharptooth: I pity you if you have to use Visual Studio. I have long ago stopped caring about Microsoft's poor support for C++: I just shunned it. – Matthieu M. Feb 01 '12 at 12:52
0

Yes.

Anytime you create a class with a virtual function you need to declare the destructor also as virtual.

Consider this situation -

base *b = new der();
delete b;

Since you are operating on the base pointer, it doesn't know that it is actually an object of the child class and hence the destructor of the der is never called. Which might invaraibly lead memory leaks among other issues.

bluefalcon
  • 4,225
  • 1
  • 32
  • 41
  • Wrong. Even if the base class doesn't have any virtual function, it is [UB do delete an instance of the derived class through the base pointer](https://stackoverflow.com/a/4178919/7571258). – zett42 Oct 18 '18 at 12:05