Do virtual destructors have to be public? - c++

I find that almost every code snippet of virtual destructors has it as public member function, like this:
class Base
{
public:
virtual ~Base()
{
cout << "~Base()" << endl;
}
};
class Derived : public Base
{
public:
~Derived()
{
cout << "~Derived()" << endl;
}
};
Do virtual destructors have to be public or are there situations where a non-public virtual destructor makes sense?

Do virtual destructors have to be public or are there situations where a non-public virtual destructor makes sense?
Horses for courses. You use a public virtual destructor if you need polymorphic deletion if not then your destructor does not need to be virtual at all.
Follow Herb's advice:
Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual.
In brief, then, you're left with one of two situations. Either:
You want to allow polymorphic deletion through a base pointer, in which case the destructor must be virtual and public; or
You don't, in which case the destructor should be nonvirtual and protected, the latter to prevent the unwanted usage.

Just as non-virtual destructors, no they need not be public, but most of the time they are.
If your class is an exception to the rule and needs to take control of the lifetime of its instances for any reason then the destructor has to be non-public. This will affect how clients can (or cannot) utilize instances of the class, but that's of course the whole point. And since the destructor is virtual, the only other option would be virtual protected.
Related: Is there a use for making a protected destructor virtual?

If you plan to create/destroy objects via special methods (for example, create/destroy), it is not necessary. But if you create your object on stack or heap, you have to have public destructor.

The question here is about a virtual destructor, hence I assume the permutations of reasons on why such implementation is needed should include inheritance cases as well. The answer for the question depends on the following:
1) You may use a private constructor/destructor if you don't want class to be instantiated. Though, The instantiation can be done by another method in the same class. So, when you want to use a specific method like MyDestructor() within the class to call the destructor, a destructor can still be put under private.
For Ex: Singleton design pattern. Also, in this case, it prevents the class from being inherited
2) If at all the class is intended to be inherited, Private base class destructor cannot be allowed (throws a compile error).But, a protected base class destructor allows inheritance
3) The type of inheritance (public and protected) of a protected virtual destructor allows a safe way of multi level inheritance A->B->C so that when the destructor of C is called, the memory is cleaned up better.
4) A private destructor alone cannot allow delete for (I'm not sure about the auto_ptr, but I think even that should adhere to the same thought of using a "private" destructor) when the memory is dynamically allocated using new.
All around, I see using a private destructor may be error prone, especially, when someone who's not aware of such implementation is about to use such a class.
protected and public destructors are always welcome and the usage depends on the needs as given above.
Hope this clarifies.

There are two separate rules involved here. First, if your design calls for deleting objects of a derived type through a pointer to a base, the destructor in the base must be virtual. Second, if a member function (and by that I broadly include the destructor) is protected or private, then the contexts in which it can be called are more restricted than when it's public (of course, if the destructor is private, you can't derived from the class). For example:
class C {
protected:
virtual ~C();
friend void destroy_me(C*);
};
void destroy_me(C *cp) {
delete cp; // OK: destructor is accessible
}
void destroy_someone_else(C *cp) {
delete cp; // Error: destructor is not accessible
}

Related

Inheritance in c++ : destructors

I added a protected member array in the abstract base class that each derived class uses, should the destructor of the base class be virtual or can I do:
**~base(){
delete[] array;
}**
Both!
You can provide a definition for the base destructor (even if it's pure virtual!) and, if the base is where the resource lives, then the base is where it should be cleaned up.
Alternatively, get yourself a nice std::vector so it's all done for you.
I added a protected member array in the abstract base class that each
derived class uses, should the destructor of the base class be virtual
Yes.
When you use polymorphism desctructor should be also virtual.
There is official guideline for that:
CppCoreGuidelines/CppCoreGuidelines.md at master · isocpp/CppCoreGuidelines · GitHub
C.127: A class with a virtual function should have a virtual or protected destructor
Reason
A class with a virtual function is usually (and in general) used via a pointer to base. Usually, the last user has to call delete on a pointer to base, often via a smart pointer to base, so the destructor should be public and virtual. Less commonly, if deletion through a pointer to base is not intended to be supported, the destructor should be protected and non-virtual; see C.35.
Example, bad
struct B {
virtual int f() = 0;
// ... no user-written destructor, defaults to public non-virtual ...
};
// bad: derived from a class without a virtual destructor
struct D : B {
string s {"default"};
};
void use()
{
unique_ptr<B> p = make_unique<D>();
// ...
} // undefined behavior, might call B::~B only and leak the string
Note
There are people who don't follow this rule because they plan to use a class only through a shared_ptr: std::shared_ptr<B> p = std::make_shared<D>(args); Here, the shared pointer will take care of deletion, so no leak will occur from an inappropriate delete of the base. People who do this consistently can get a false positive, but the rule is important -- what if one was allocated using make_unique? It's not safe unless the author of B ensures that it can never be misused, such as by making all constructors private and providing a factory function to enforce the allocation with make_shared.
Enforcement
A class with any virtual functions should have a destructor that is either public and virtual or else protected and non-virtual.
Flag delete of a class with a virtual function but no virtual destructor.

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.

virtual destructor for pure abstract class [duplicate]

This question already has answers here:
When to use virtual destructors?
(20 answers)
Closed 3 years ago.
Based on what I found here and on other links on stackoverflow, we should always define a virtual destructor in the base class if we plan to use it polymorphically. I want to know if there is an exception to this rule.
I have seen production code that does not define virtual destructor for the pure abstract base classes and in one of cppcon 2014 video Accept no visitor, around 10:06 the BoolExp struct defined is a pure abstract class and has no virtual destructor.
So for a pure abstract class defined like this
class Base {
public:
virtual foo() = 0;
virtual bar() = 0;
}
My question is it absolutely must that we define a virtual destructor for "Base" class, even though it does have any data members? Are there any exceptions to the virtual destructor rule?
Thanks in advance.
Best,
RG
My question is it absolutely must that we define a virtual destructor for "Base" class, even though it does have any data members?
It depends. If you have a case like
base * foo = new child(stuff);
// doing stuff
delete foo;
then you absolutely must have a virtual destructor. Without it you'll never destroy the child part.
If you have a case like
child * foo = new child(stuff);
// doing stuff
delete foo;
Then you do not need a virtual destructor, as child's will be called.
So the rule is if you delete polymorphically, you need a polymorphic (virtual) destructor, if not, then you don't
The exception to the rule is if you never delete an object through a pointer to the base class. In that case the base class destructor does not need to be virtual.
But if you ever delete an object via a base class pointer, then the base class destructor must be virtual or your program has Undefined Behaviour.
My question is it absolutely must that we define a virtual destructor for "Base" class, even though it does have any data members?
Stricktly speaking, No.
However, whether the base class has any member variables is not relevant. If the destructor gets called using a pointer to the base class, your code has undefined behavior regardless of whether the base class has any member variables or not.
Are there any exceptions to the virtual destructor rule?
If you are able to manage lifetimes of derived classes in such a way that the call to delete the objects is done via derived class pointers, you don't invoke undefined behavior and your code will be well behaved, assuming everything else is in your code base is in good order.
we should always define a virtual destructor in the base class if we plan to use it polymorphically.
You should always define a virtual destructor in a base classs if we plan to delete it polymorphically through that base class.
Now, one problem is that "I don't intend to" isn't safe; you should make it impossible.
Make the destructor virtual (and empty), or make it protected (and empty). A protected destructor makes polymorphic deletion unlikely (it can be bypassed, but only through pretty insane means).
Barring that, you have to be careful. This is one of the reasons why inheriting from (say) std vector is a thing to be wary of.
is it absolutely must that we define a virtual destructor for "Base" class, even though it does have any data members? Are there any exceptions to the virtual destructor rule?
It is not a must. It's a good habit that can prevent bugs.
If you decide to create a base class that doesn't have a virtual destructor, it is the responsibility of you, the developer, to always ensure that derived objects are deleted as the correct type or as a base type that does have a virtual destructor.
Deleting a derived class object using a pointer to a base class that has a non-virtual destructor results in undefined behavior. 
Otherwise you are ok to not to have virtual destructor.
I would like to make an important (at least, in my view) practical amendment to correct answers describing the deletion through base object.
In particular, the destructors are called non-virtually if object life-time is managed through std::shared_ptr<Base> allocated via
std::shared_ptr<Base> sptr = std::make_shared<Derived>(args);

Why do virtual destructors behave the way they do?

I read that that virtual destructors must be declared in classes that have virtual methods. I just cant understand why they must be declared virtual. I know why we need to have virtual destructors as from the following example. I just wanted to know why compilers dont manage virtual destructors for us. Is there something I need to know about working of virtual destructors ?
The following example shows that if destructors are not declared virtual the destructors of derived class are not called why is that ?
class Base
{
// some virtual methods
public:
Base()
{std::cout << "Base Constructor\n";}
~Base()
{std::cout << "Base De-structor\n";}
};
class Derived : public Base
{
public:
Derived()
{std::cout << "Der constructor\n";}
~Derived()
{ std::cout << "Der De-structor\n";}
} ;
void main()
{
Base *b = new Derived();
delete b;
}
I just wanted to know why compilers dont manage virtual destructors for us.
Because in C++, you pay for what you use. Having a virtual destructor by default involves the compiler adding a virtual table pointer to the class, which increases its size. This is not always desirable.
The following example shows that if destructors are not declared virtual the destructors of derived class are not called why is that ?
The example exibits undefined behavior. It's simply against the rules. The fact that not all destructors are called is just one possible manifestation. It could possibly crash.
Is there something I need to know about working of virtual destructors ?
Yes. They are required if you're deleting an object through a pointer to a base class. Otherwise it's undefined behavior.
5.3.5 Delete [expr.delete]
3) In the first alternative (delete object), if the static type of the object to be deleted is different from its
dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the
static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete
array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined. (emphasis mine)
I read that that virtual destructors must be declared in classes that have virtual methods.
"must" is too strong a word: "should" fits much better into that advise.
I just wanted to know why compilers dont manage virtual destructors for us.
C++ designers tried to avoid compiler doing things that you did not ask it to do only under the most extreme circumstances. Language designers recognized that the decision to make a class polymorphic should rest with the designer of the program, so they refused to re-assign this responsibility to the compiler.
The following example shows that if destructors are not declared virtual the destructors of derived class are not called why is that?
Because your code is invalid: by declaring the destructor of Derived non-virtual you made a promise to never destroy Derived through a pointer to Base; your main breaks this promise, invoking undefined behavior.
Note that by merely declaring your b variable with the exact type you would have avoided the problem associated with the non-virtual destructor (link to ideone). However, this leads to a rather shaky design, so you should avoid inheritance hierarchies with virtual functions and non-virtual destructors.
I read that that virtual destructors must be declared in classes that have virtual methods.
Yes. But that is an oversimplification.
Its not that a class with virtual methods needs a virtual destructor. But the way a class with virtual methods is used means that it will usually need a virtual destructor. A virtual destructor is ONLY needed if you delete an object via a pointer to its base class. The problem is that when an object has virtually methods you are usually working with a pointer to its base class even though the actual object is slightly different.
I just cant understand why they must be declared virtual.
It's not that they must. As explained above. This is a result of the usual usage patterns.
I just wanted to know why compilers dont manage virtual destructors for us.
Because it is not always needed. And the ethos of C++ is you don't have to pay for something you don't need it. If the compiler always added virtual destructors to a class with virtual methods then I would have to pay the price of using a virtual destructor even in situations I can prove in my code base that I don't need it.
Is there something I need to know about working of virtual destructors ?
Just that there is a slight cost to using them.
if destructors are not declared virtual the destructors of derived class are not called why is that ?
That is why we have virtual destructors to cause this behavior. If you need this behavior you need to add virtual destructors. But there are cases were virtual destructors may not be required which allows the user of this method not to pay the price.

Virtual destructor for boost:noncopyable classes?

I have a question about the following code:
class MyClass : private boost::noncopyable
{
public:
MyClass() {}
virtual ~MyClass() {}
}
class OtherClass : private boost::noncopyable
{
private:
MyClass* m_pMyClass;
}
My thoughts are that MyClass cannot be copied using construction or assignment. Using a virtual destructor is needed if I want to support deriving classes from MyClass, which I do not want to support. I do not intend to create pointers to this class and pass them around.
I do not want a Singleton and I cannot see a downside to removing the virtual destructor.
Do I introduce a potential problem if remove the virtual destructor for a noncopyable class? Are there a better practices to handle a class that does not need to be a Singleton, but I only want one instance in another class and not support inheritance?
No, the entire point of a virtual destructor is so derived classes can properly destruct polymorphically. If this will never be a base class, you don't need it to be virtual.
The general rule is if your class has virtual functions it needs a virtual destructor. If it doesn't, but is still derived from a base class, the base class (and hence your class) may or may not need a virtual destructor depending.
Deriving your class from boost::noncopyable doesn't really count as being derived from a base class. boost::noncopyable is more like a convenient annotation backed up with a couple of declarations that will cause the compiler to enforce the annotation. It's not really a base class in any conventional sense. Nobody is ever going to try to pass around a pointer to your class as a pointer or reference to boost::noncopyable. And even if they did your virtual destructor wouldn't help because the boost::noncopyable's destructor isn't.
And lastly, as was pointed out in a comment, you are even privately inheriting from boost::noncopyable so it's not even really inheritance at all as far as anybody outside the class is concerned.
So really, no need to make it a virtual destructor.
I'm really not a fan of the boost::noncopyable class as a whole. Why not just declare your class's copy constructor and assignment operator private and not define them. That will accomplish the same thing, and you can ditch the virtual destructor.
Boost only supplies a virtual destructor so that people can pass around boost::noncopyable objects polymorphic and still have them behave well. Technically speaking if you are not going to use the class polymorphically (you can even still inherit from it), you really don't need a virtual destructor.
Virtual destructor in base class is used to avoid partial destruction problem like :
Base *pBase = new Derived();
delete pBase;
//if destructor is not made virtual then derived class destructor will never called.
When you inherit a class privately , compiler won't perform implicit casting from derived to base class and if you are sure that derived object is never destructed using base class pointer then you don't need virtual destructor in base class.
Base *pBase = new Derived(); // will flash error
boost::noncopyable is meant to say that you don't want copies of the object made. You're aware that this is different from deriving from the object.
It is perfectly fine to get rid of the virtual destructor if you won't ever derive from the object. If you want to enforce the "don't derive from this object" policy, there is a way. Unfortunately, there is no boost::nonderivable to pretty this up for you.
As mentioned in the link, C++11 allows you to declare the class final:
class MyClass : final private boost::noncopyable { ... };