Why should the destructor of base classes be virtual? - c++

in C++: Why should the destructor of base classes be virtual?

The better question is when and why. Your question indicates that you think all base classes should have virtual destructors, which is not quite true.
It would make it impossible to apply the empty base class optimization, and could multiply the size of classes up to 16 times than what it would be without virtual on common platforms.
A virtual destructor is needed when you delete an object whose dynamic type is DerivedClass by a pointer that has type BaseClass*. The virtual makes the compiler associate information in the object making it able to execute the derived class destructor. Missing the virtual in such case causes undefined behavior.
If you don't need this, and your class is only used as a base class, it's best to make the destructor protected, thus preventing that users accidentally delete in the described way.

You want them to be virtual so that all subclass destructors are automatically called when the object is destroyed, even if it is destroyed through a pointer to the base class. In the following code:
class base {
public:
virtual ~base() { }
};
class derived : public base {
public:
~derived() { } // Inherits the virtual designation
};
int main(void)
{
base *b = new derived;
delete b;
}
The derived destructor will only be called if the base destructor is virtual.
As Magnus indicates, you don't have to do this if you aren't taking advantage of polymorphism. However, I try to develop the habit of declaring all my destructors virtual. It protects me against the case where I should have declared them virtual but forget to do so. As Johannes indicates, this habit can impose a small space and performance penalty when the virtual designation is not needed.

They dont have to be virtual unless you are using polymorphism. If you do use polymorphism they need to be virtual so that the destructors of inherited classes are guaranteed to be called, so inherited classes can do their clean up.

For situations like this:
class A
{
virtual ~A();
};
class B:A
{
~B();
};
A *a = new B(); //legal, since it's a downcast
delete a; //Unless the destructor is virtual, ~A() is called here instead of ~B().

It should be virtual to ensure that the destructor of the inherited classes are the ones actually getting called at runtime instead of the base class destructor being called.

Related

Destructor is not called in Factory Pattern [duplicate]

I know it is a good practice to declare virtual destructors for base classes in C++, but is it always important to declare virtual destructors even for abstract classes that function as interfaces? Please provide some reasons and examples why.
It's even more important for an interface. Any user of your class will probably hold a pointer to the interface, not a pointer to the concrete implementation. When they come to delete it, if the destructor is non-virtual, they will call the interface's destructor (or the compiler-provided default, if you didn't specify one), not the derived class's destructor. Instant memory leak.
For example
class Interface
{
virtual void doSomething() = 0;
};
class Derived : public Interface
{
Derived();
~Derived()
{
// Do some important cleanup...
}
};
void myFunc(void)
{
Interface* p = new Derived();
// The behaviour of the next line is undefined. It probably
// calls Interface::~Interface, not Derived::~Derived
delete p;
}
The answer to your question is often, but not always. If your abstract class forbids clients to call delete on a pointer to it (or if it says so in its documentation), you are free to not declare a virtual destructor.
You can forbid clients to call delete on a pointer to it by making its destructor protected. Working like this, it is perfectly safe and reasonable to omit a virtual destructor.
You will eventually end up with no virtual method table, and end up signalling your clients your intention on making it non-deleteable through a pointer to it, so you have indeed reason not to declare it virtual in those cases.
[See item 4 in this article: http://www.gotw.ca/publications/mill18.htm]
I decided to do some research and try to summarise your answers. The following questions will help you to decide what kind of destructor you need:
Is your class intended to be used as a base class?
No: Declare public non-virtual destructor to avoid v-pointer on each object of the class *.
Yes: Read next question.
Is your base class abstract? (i.e. any virtual pure methods?)
No: Try to make your base class abstract by redesigning your class hierarchy
Yes: Read next question.
Do you want to allow polymorphic deletion through a base pointer?
No: Declare protected virtual destructor to prevent the unwanted usage.
Yes: Declare public virtual destructor (no overhead in this case).
I hope this helps.
* It is important to note that there is no way in C++ to mark a class as final (i.e. non subclassable), so in the case that you decide to declare your destructor non-virtual and public, remember to explicitly warn your fellow programmers against deriving from your class.
References:
"S. Meyers. More Effective C++, Item 33 Addison-Wesley, 1996."
Herb Sutter, Virtuality, 2001
C++ Faq, 20.7, "When should my destructor be virtual?"
The answers to this question, of course.
Yes it is always important. Derived classes may allocate memory or hold reference to other resources that will need to be cleaned up when the object is destroyed. If you do not give your interfaces/abstract classes virtual destructors, then every time you delete a derived class instance via a base class handle your derived class' destructor will not be called.
Hence, you're opening up the potential for memory leaks
class IFoo
{
public:
virtual void DoFoo() = 0;
};
class Bar : public IFoo
{
char* dooby = NULL;
public:
virtual void DoFoo() { dooby = new char[10]; }
void ~Bar() { delete [] dooby; }
};
IFoo* baz = new Bar();
baz->DoFoo();
delete baz; // memory leak - dooby isn't deleted
It is not always required, but I find it to be good practice. What it does, is it allows a derived object to be safely deleted through a pointer of a base type.
So for example:
Base *p = new Derived;
// use p as you see fit
delete p;
is ill-formed if Base doesn't have a virtual destructor, because it will attempt to delete the object as if it were a Base *.
It's not only good practice. It is rule #1 for any class hierarchy.
The base most class of a hierarchy in C++ must have a virtual destructor
Now for the Why. Take the typical animal hierarchy. Virtual destructors go through virtual dispatch just as any other method call. Take the following example.
Animal* pAnimal = GetAnimal();
delete pAnimal;
Assume that Animal is an abstract class. The only way that C++ knows the proper destructor to call is via virtual method dispatch. If the destructor is not virtual then it will simply call Animal's destructor and not destroy any objects in derived classes.
The reason for making the destructor virtual in the base class is that it simply removes the choice from derived classes. Their destructor becomes virtual by default.
The answer is simple, you need it to be virtual otherwise the base class would not be a complete polymorphic class.
Base *ptr = new Derived();
delete ptr; // Here the call order of destructors: first Derived then Base.
You would prefer the above deletion, but if the base class's destructor is not virtual, only the base class's destructor will be called and all data in derived class will remain undeleted.

Is it safe to initialize an auto_ptr with a pointer to a derived class?

Lets say I have a base class and a derived class:
class Base
{
public:
virtual ~Base() {}
virtual void DoSomething() = 0;
};
class Child : public Base
{
public:
virtual void DoSomething()
{
// Do Something
}
};
Is it safe to initialize an std::auto_ptr of the type of the base class with a pointer to an instance of the derived class? I.E. will an object created like this:
std::auto_ptr<Base> myObject(new Derived());
correctly call the destructor of the derived class instead of the base class without leaking memory?
Despite the fact that you shouldn't use std::auto_ptr anymore since the arrival of C++11;
Yes, this is safe as long as your base has a virtual destructor.
Without the virtual destructor on the base, (like Steve Jessop noted below) you would get undefined behavior, since the destructor of the deriving class would be unknown at the time of destruction, and hence not being executed. This is a dangerous problem since in many cases it stays unnoticed. E.g., if you would manage some kind of resource in a single-inheritance class, that should have been freed in the destructor, a leak would occur silently.
Perfectly safe.
Many references are available - try searching for "auto_ptr polymorphism".
e.g. http://www.devx.com/tips/Tip/14391
As long as your class Base the std::auto_ptr<Base> is parameterized with has a virtual destructor you can initialize the std::auto_ptr<Base> with classes derived of Base and they will be properly destroyed if the std::auto_ptr<Base> destructor is instantiated when a definition of Base is visible.

why to declare a virtual destructor C++? [duplicate]

I know it is a good practice to declare virtual destructors for base classes in C++, but is it always important to declare virtual destructors even for abstract classes that function as interfaces? Please provide some reasons and examples why.
It's even more important for an interface. Any user of your class will probably hold a pointer to the interface, not a pointer to the concrete implementation. When they come to delete it, if the destructor is non-virtual, they will call the interface's destructor (or the compiler-provided default, if you didn't specify one), not the derived class's destructor. Instant memory leak.
For example
class Interface
{
virtual void doSomething() = 0;
};
class Derived : public Interface
{
Derived();
~Derived()
{
// Do some important cleanup...
}
};
void myFunc(void)
{
Interface* p = new Derived();
// The behaviour of the next line is undefined. It probably
// calls Interface::~Interface, not Derived::~Derived
delete p;
}
The answer to your question is often, but not always. If your abstract class forbids clients to call delete on a pointer to it (or if it says so in its documentation), you are free to not declare a virtual destructor.
You can forbid clients to call delete on a pointer to it by making its destructor protected. Working like this, it is perfectly safe and reasonable to omit a virtual destructor.
You will eventually end up with no virtual method table, and end up signalling your clients your intention on making it non-deleteable through a pointer to it, so you have indeed reason not to declare it virtual in those cases.
[See item 4 in this article: http://www.gotw.ca/publications/mill18.htm]
I decided to do some research and try to summarise your answers. The following questions will help you to decide what kind of destructor you need:
Is your class intended to be used as a base class?
No: Declare public non-virtual destructor to avoid v-pointer on each object of the class *.
Yes: Read next question.
Is your base class abstract? (i.e. any virtual pure methods?)
No: Try to make your base class abstract by redesigning your class hierarchy
Yes: Read next question.
Do you want to allow polymorphic deletion through a base pointer?
No: Declare protected virtual destructor to prevent the unwanted usage.
Yes: Declare public virtual destructor (no overhead in this case).
I hope this helps.
* It is important to note that there is no way in C++ to mark a class as final (i.e. non subclassable), so in the case that you decide to declare your destructor non-virtual and public, remember to explicitly warn your fellow programmers against deriving from your class.
References:
"S. Meyers. More Effective C++, Item 33 Addison-Wesley, 1996."
Herb Sutter, Virtuality, 2001
C++ Faq, 20.7, "When should my destructor be virtual?"
The answers to this question, of course.
Yes it is always important. Derived classes may allocate memory or hold reference to other resources that will need to be cleaned up when the object is destroyed. If you do not give your interfaces/abstract classes virtual destructors, then every time you delete a derived class instance via a base class handle your derived class' destructor will not be called.
Hence, you're opening up the potential for memory leaks
class IFoo
{
public:
virtual void DoFoo() = 0;
};
class Bar : public IFoo
{
char* dooby = NULL;
public:
virtual void DoFoo() { dooby = new char[10]; }
void ~Bar() { delete [] dooby; }
};
IFoo* baz = new Bar();
baz->DoFoo();
delete baz; // memory leak - dooby isn't deleted
It is not always required, but I find it to be good practice. What it does, is it allows a derived object to be safely deleted through a pointer of a base type.
So for example:
Base *p = new Derived;
// use p as you see fit
delete p;
is ill-formed if Base doesn't have a virtual destructor, because it will attempt to delete the object as if it were a Base *.
It's not only good practice. It is rule #1 for any class hierarchy.
The base most class of a hierarchy in C++ must have a virtual destructor
Now for the Why. Take the typical animal hierarchy. Virtual destructors go through virtual dispatch just as any other method call. Take the following example.
Animal* pAnimal = GetAnimal();
delete pAnimal;
Assume that Animal is an abstract class. The only way that C++ knows the proper destructor to call is via virtual method dispatch. If the destructor is not virtual then it will simply call Animal's destructor and not destroy any objects in derived classes.
The reason for making the destructor virtual in the base class is that it simply removes the choice from derived classes. Their destructor becomes virtual by default.
The answer is simple, you need it to be virtual otherwise the base class would not be a complete polymorphic class.
Base *ptr = new Derived();
delete ptr; // Here the call order of destructors: first Derived then Base.
You would prefer the above deletion, but if the base class's destructor is not virtual, only the base class's destructor will be called and all data in derived class will remain undeleted.

Destructors for C++ Interface-like classes

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)
A base class destructor should be either public and virtual, or protected and nonvirtual.
(Herb Sutter, Guru of the Week #18: "Virtuality")
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()
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.
A class with virtual functions but no virtual destructor is suspect, and most likely wrong: see a good and more precise explanation here.
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.
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.

Why should I declare a virtual destructor for an abstract class in C++?

I know it is a good practice to declare virtual destructors for base classes in C++, but is it always important to declare virtual destructors even for abstract classes that function as interfaces? Please provide some reasons and examples why.
It's even more important for an interface. Any user of your class will probably hold a pointer to the interface, not a pointer to the concrete implementation. When they come to delete it, if the destructor is non-virtual, they will call the interface's destructor (or the compiler-provided default, if you didn't specify one), not the derived class's destructor. Instant memory leak.
For example
class Interface
{
virtual void doSomething() = 0;
};
class Derived : public Interface
{
Derived();
~Derived()
{
// Do some important cleanup...
}
};
void myFunc(void)
{
Interface* p = new Derived();
// The behaviour of the next line is undefined. It probably
// calls Interface::~Interface, not Derived::~Derived
delete p;
}
The answer to your question is often, but not always. If your abstract class forbids clients to call delete on a pointer to it (or if it says so in its documentation), you are free to not declare a virtual destructor.
You can forbid clients to call delete on a pointer to it by making its destructor protected. Working like this, it is perfectly safe and reasonable to omit a virtual destructor.
You will eventually end up with no virtual method table, and end up signalling your clients your intention on making it non-deleteable through a pointer to it, so you have indeed reason not to declare it virtual in those cases.
[See item 4 in this article: http://www.gotw.ca/publications/mill18.htm]
I decided to do some research and try to summarise your answers. The following questions will help you to decide what kind of destructor you need:
Is your class intended to be used as a base class?
No: Declare public non-virtual destructor to avoid v-pointer on each object of the class *.
Yes: Read next question.
Is your base class abstract? (i.e. any virtual pure methods?)
No: Try to make your base class abstract by redesigning your class hierarchy
Yes: Read next question.
Do you want to allow polymorphic deletion through a base pointer?
No: Declare protected virtual destructor to prevent the unwanted usage.
Yes: Declare public virtual destructor (no overhead in this case).
I hope this helps.
* It is important to note that there is no way in C++ to mark a class as final (i.e. non subclassable), so in the case that you decide to declare your destructor non-virtual and public, remember to explicitly warn your fellow programmers against deriving from your class.
References:
"S. Meyers. More Effective C++, Item 33 Addison-Wesley, 1996."
Herb Sutter, Virtuality, 2001
C++ Faq, 20.7, "When should my destructor be virtual?"
The answers to this question, of course.
Yes it is always important. Derived classes may allocate memory or hold reference to other resources that will need to be cleaned up when the object is destroyed. If you do not give your interfaces/abstract classes virtual destructors, then every time you delete a derived class instance via a base class handle your derived class' destructor will not be called.
Hence, you're opening up the potential for memory leaks
class IFoo
{
public:
virtual void DoFoo() = 0;
};
class Bar : public IFoo
{
char* dooby = NULL;
public:
virtual void DoFoo() { dooby = new char[10]; }
void ~Bar() { delete [] dooby; }
};
IFoo* baz = new Bar();
baz->DoFoo();
delete baz; // memory leak - dooby isn't deleted
It is not always required, but I find it to be good practice. What it does, is it allows a derived object to be safely deleted through a pointer of a base type.
So for example:
Base *p = new Derived;
// use p as you see fit
delete p;
is ill-formed if Base doesn't have a virtual destructor, because it will attempt to delete the object as if it were a Base *.
It's not only good practice. It is rule #1 for any class hierarchy.
The base most class of a hierarchy in C++ must have a virtual destructor
Now for the Why. Take the typical animal hierarchy. Virtual destructors go through virtual dispatch just as any other method call. Take the following example.
Animal* pAnimal = GetAnimal();
delete pAnimal;
Assume that Animal is an abstract class. The only way that C++ knows the proper destructor to call is via virtual method dispatch. If the destructor is not virtual then it will simply call Animal's destructor and not destroy any objects in derived classes.
The reason for making the destructor virtual in the base class is that it simply removes the choice from derived classes. Their destructor becomes virtual by default.
The answer is simple, you need it to be virtual otherwise the base class would not be a complete polymorphic class.
Base *ptr = new Derived();
delete ptr; // Here the call order of destructors: first Derived then Base.
You would prefer the above deletion, but if the base class's destructor is not virtual, only the base class's destructor will be called and all data in derived class will remain undeleted.