30

Starting to use PC-Lint on an existing code base (fear and trepidation).

One thing that it complains about is the following:

 class IBatch
 {
 public:
    virtual void StartBatch() =0;
    virtual int CommitBatch() =0;
 };

Which when another class derives from this to use it like an interface

base class 'IBatch' has no destructor

So, the question: when you create Interface classes like the above, do you always include a virtual destructor? Why? (is it a style or a coding error?)

EDIT: Should have said that I do not expect or want the user of IBatch to destruct, they are a consumer of a service only, through this interface to some external implementing class (if that would make a difference)

sdg
  • 4,645
  • 3
  • 32
  • 26
  • 1
    As other said, you need a virtual DTor. Just as side note: COM interfaces instead rely on `Release()`, which is a virtual method that can redirect to an "appropriate" derived DTor. – peterchen Apr 22 '10 at 15:15

6 Answers6

34

A base class destructor should be either public and virtual, or protected and nonvirtual.

(Herb Sutter, Guru of the Week #18: "Virtuality")

James McNellis
  • 348,265
  • 75
  • 913
  • 977
12

Coding error - The destructor for your derived class will never get called if called via pointer to base class.

When you implement IBatch and you refer to your derived class by a pointer to a base class (pointer to IBatch) and you call delete on that pointer to base class you might end up with memory leak because the destructor for your derived class will never get called.

The basic rule is when a class has at least one virtual method it needs to have virtual destructor.

class IBatch
{
    public:
       virtual void f() = 0;
};

class A : public IBatch
{
    public:
       void f() {}
       ~A() {}
};

IBatch * a = new A();
a->f();    // calls A::f()
delete a;  // calls IBatch::~IBatch() not A::~A()
stefanB
  • 77,323
  • 27
  • 116
  • 141
  • 3
    What if I don't want users of the IBatch interface to call delete on me - is that where the protected and non-virtual answer from @James comes in? – sdg Apr 22 '10 at 15:28
  • 2
    @sdg: Yes. A protected destructor prevents *other* classes (outside that class hierarchy) from calling delete on it. – Kissaki Apr 24 '13 at 14:36
8

If there are virtual functions, there needs to be a virtual destructor. Always. It does not matter that it's only an interface class -- it still needs the virtual destructor.

Either that, or it needs a protected nonvirtual destructor. But then you cannot delete the object using the interface pointer.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
5

A class with virtual functions but no virtual destructor is suspect, and most likely wrong: see a good and more precise explanation here.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
4

So, the question: when you create Interface classes like the above, do you always include a virtual destructor? Why? (is it a style or a coding error?)

Well it depends really. If you ever call delete on an IBatch pointer it probably won't do what you are expecting. Of course if you have something like virtual Init/Shutdowns or AddRef/Releases then its not really a problem.

Goz
  • 61,365
  • 24
  • 124
  • 204
0

Compiler puts default destructor that is not virtual, which implies that a 'delete' on a pointer to the virtual base class will succeed with a resulting memory leak. Therefore, it is an implementation flaw, neither style or coding error.

baris.aydinoz
  • 1,902
  • 2
  • 18
  • 28
  • Actually, deleting a derived object with virtual functions through a pointer to a base class without a virtual destructor is undefined behavior. So it is a coding error, and anything can happen including a memory leak, program crash, or a case of nasal demons. – KeithB Apr 22 '10 at 16:29