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 { ... };
Related
So I'm studying for an C++ exam and I've come across the following question:
If you were to inherit from std::vector would you create a virtual
destructor?
Since std::vector does not have a virtual destructor would there be any point in me creating one?
I think std::vector is a red herring. First let me rewrite the question as
If you were to write a class A that inherits from std::vector, would you give it a virtual destructor?
Then the only relevant thing here is whether std::vector does already have a virtual destructor. If it had, the destructor of A would always be virtual automatically, no matter whether you specify it with the virtual keyword or not. But std::vector does not have a virtual destructor. So the reference to it can be dropped:
If you were to write a class A, would you give it a virtual destructor?
The answer would still be that it will be automatically virtual if A inherits from any other class with virtual destructor, so the only interesting case left is:
If you were to write a class A, which does not inherit from any class with virtual destructor, would you give it a virtual destructor?
Now this is a very general question and as mentioned in the comments, it depends on whether you intend to use the class as polymorphic base, i.e. whether you want to allow deletion of objects of a type derived from A through a pointer/reference to A.
A class needs a virtual destructor if your design calls for deleting an object of a type derived from that class through a pointer to that class. That is,
class base {
};
class derived : public base {
};
void f() {
base *bp = new derived;
delete bp; // undefined behavior: base does not have a virtual destructor
}
std::vector, by design does not have a virtual destructor. It is not intended to be used as a base class.
So if your (flawed) design calls for deriving from std::vector<whatever> and deriving from your derived type and deleting objects of your ultimate type through pointers to your base type, then your base type must have a virtual destructor. But that has nothing to do with std::vector or with the fact that your base type is derived from std::vector. It's needed because of the way your base class is used.
In terms of inheritance, I understand that it's advised for your classes' destructors to be virtual, so the base class's destructor gets called correctly in addition to any derived destructors. However, I'm wondering if there are any stack-related issues that relate to derived objects in the following scenario.
Let's suppose we have a Base class that doesn't have a destructor (for whatever reason):
class Base{};
and a Derived class that DOES have a destructor:
class Derived : public Base
{
~Derived(){}
};
And in the main...:
int main()
{
Derived a;
return 0;
}
Do I run into any issues from the Base class not having a destructor? My initial guess is that the compiler will just generate a default destructor for the Base class. Again, my question is mostly related to the stack rather than dynamic memory: is there any weirdo scenario I need to look out for in order to avoid a Derived destructor being called and the Base destructor is not?
The rule you're thinking of is that if you delete an object of a derived type through a pointer to one of its base types and that base type does not have a virtual destructor the behavior is undefined. The code here doesn't delete anything, so the rule does not apply.
To ensure safety, it is sufficient that every destructor (implicit or explicit) be at least one of:
virtual (for base classes if you need to delete subclass instances through base class pointers)
protected (to ensure that it is impossible to attempt to delete through a base class pointer)
final (actually an attribute of the class, to avoid the entire possibility of subclasses).
There are a few rare edge cases where it is possible to safely call destructors, but they are generally a sign of bad design and are easy to avoid if you manage to happen across one of them.
As an aside, note that std::shared_ptr type-erases its deleter, so std::shared_ptr<Base> will work even if Base does not have a public destructor.
Your base class has an implicit destructor. All will be fine.
A virtual base class destructor is used to allow a derived constructor to run when destructing via a pointer or reference to the base class. So in your case, this would be unsafe:
void destruct(Base &b) { b.~Base(); }
Derived d; destruct(d);
But this will be perfectly safe:
void destruct(Derived &d) { d.~Derived(); }
Derived d; destruct(d);
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
}
On a project, I have the following problem :
I have a very simple inheritance scheme (I need inheritance and not composition) :
class Base
-> class DerivedA
-> class DerivedB
-> class DerivedC
A, B and C derive from Base and that's all.
So now I have 2 choices :
public inheritance with virtuality
private inheritance without virtuality
For some optimization reasons (I need a lot of inlining) I don't want virtuality ... and I don't want private inheritance. I think that the only option that remains is CRTP. But the base class have like 300 functions and implementing CRTP in it will be a real pain.
So I wonder if the following solution is valid : I use CRTP only in the destructor of the base class :
template<class TCRTP> class Base
{
~Base() {delete static_cast<TCRTP*>(this);}
}
where TCRTP will be DerivedA, B or C and I do public inheritance.
Is it perfectly ok, or problematic ?
Thank you very much.
Your destructor is definitely wrong. The destructor of a class does not and must not delete the memory for the object.
What's your objection to public inheritance without virtual functions? There are (at least) a couple of ways to prevent someone accidentally deleting a derived object through a base pointer. One is to make the base destructor protected.
Another is to stuff dynamically-allocated instances of the derived class straight into a shared_ptr. This can even be a shared_ptr<Base>:
std::shared_ptr<Base> foo(new DerivedA(...));
Because shared_ptr has a template constructor that captures the type of its argument, the Base* pointer will be converted to DerivedA* in the deleter function associated with the shared_ptr, and hence deleted correctly. Nobody should ever be so daft as to try to extract a pointer out of a shared_ptr and delete it as Base*.
Of course if you have no virtual functions, then the trick is only really useful when the only difference between the derived classes is what they set up in their constructors. Otherwise you'll end up needing to downcast the Base* pointer from the shared_ptr, in which case you should have used a shared_ptr<DerivedA> to begin with.
I could see using code like inside the implementation of IUnknown::Release, but never in a destructor. The Base destructor only runs after the derived object has been destroyed, trying to delete the derived object at that point is undefined behavior. I'm pretty sure you'd get infinite recursion in that particular case.
This example below illustrates how to prevent derived class from being copied. It's based on a base class where both the copy constructor and copy assignment operator are declared private.
class Uncopyable
{
protected:
// allow construction and destruction of derived objects...
Uncopyable() {}
~Uncopyable() {}
private:
// but prevent copying...
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
We can use this class, combined with private inheritance, to make classes uncopyable:
class derived: private Uncopyable
{...};
Notice that the destructor in class Uncopyable is not declared as virtual.
Previously, I learned that
Destructors in base classes should be virtual.
Destructors in non-base classes should not be made virtual.
In this example, the destructor for Uncopyable is not virtual, but it is being inherited from. This seems to go against the wisdom I've learned previously.
When and why should destructor in base class NOT be defined as virtual?
A base class destructor only needs to be virtual if you might try deallocating an object of a derived type through a pointer of the base type. Consequently, if you only inherit from the base class privately instead of publicly, as would be the case in Uncopyable, then you don't need to worry about putting in a virtual destructor, because when using private inheritance you can't get a pointer to the derived object and store it in a pointer to the base type.
Another example might be if you were to use a mixin class like this one that makes a class track the number of object allocations, where the mixin is inherited from to acquire behavior but not to be treated polymorphically:
template <typename T> class Counter {
public:
Counter() { ++numInstances; }
Counter(const Counter&) { ++numInstances );
~Counter() { --numInstances; }
static unsigned getNumInstances() { return numInstances; }
private:
static unsigned numInstances;
}
template <typename T> unsigned Counter<T>::numInstances = 0;
More generally, when using static polymorphism, you don't need virtual destructors because you never treat the classes polymorphically using pointers to the base type. You only use a pointer to the derived type.
There are probably a few other cases I didn't cover here, but these two (private inheritance, mixin classes, and static polymorphism) cover much of the space where virtual destructors aren't required.
When you design the base not as interface, but as implementation detail (note the private inheritance from Uncopyable).
You technically don't have to make your decostructor virtual if you know nobody will delete it as a Uncopyable*, but will always delete it as a subclass of the same.
Yes this is essentially, what #templatetypedef said, but I'm going to explain it in a maybe easier way.
So: if people might do something like this:
void aFunction(Uncopyable* obj) {
delete obj;
}
Then you should declare your destructor virtual (to make sure potential subclasses get their destructor called.
However, if you know people will be deleting Subclasses like so:
class Widget : public Uncopyable
{
....
};
void aFunction(Widget* obj) {
delete obj;
}
Then you don't have to make your destructor virtual (as the subclasses destructor will be called).
At least, that's my understanding.
When you need your objects to be plain old data, with no vtable. I'd comment the heck out of it if I ever needed it, as 99% of the time leaving off the 'virtual' in base class destructors is simply a mistake that someone will want to correct.
The general rule is to make your destructor public and virtual, or protected and non-virtual. In the first case, your object use destroyable polymorphically and teh virtual destructor will do the right thing. In the second case it will only be destroyed as the actual child class and still do the right thing.