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.
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);
Looking at the C++ language standard, is there any way to call only derived class destructor, without calling destructor of the base class?
So, for classes
class Base { public: virtual ~Base() {} };
class Derived : public Base { public: ~Derived();};
if would be possible to write code like
Base *basePtr = new Derived();
//do something with basePtr
// Now somehow destroy Derived while keeping Base - call ~Derived() only,
// line below however will call both ~Derived() and ~Base() - how it can be done?
dynamic_cast<Derived*>(basePtr)->~Derived();
So, after execution of the code above basePtr will point to Base object only, like if it was created by
Base *basePtr = new Base();
plus any modifications to the Base object caused by manipulating basePtr between calling new Derived() and destroying Derived class?
Or, is this forbidden and it is impossible to do?
No, this is not possible. The standard demands that the destruction of a Derived object destroys the whole object, including the Base subobject. Anything else would not be a destruction according to C++'s understanding of object lifetime.
Depending on what you want to achieve, consider to copy the Base out of the derived first
std::unique_ptr<Base> basePtr(new Derived());
//do something with basePtr
basePtr.swap(std::unique_ptr<Base> (new Base(*basePtr))); //splice the Base part out of the derived object
//basePtr now points to the spliced Base object.
Another approach would be to hold the additional members that derived has in a boost::optional (or just a pimpl) and reset that to get a "stripped" Derived object that still has its Base class part. This will however not affect virtual function dispatch.
As you have formulated the question, it is not possible to achieve what you are asking for. Unless you have a memory leak, the only case when explicitly calling a destructor does not lead to undefined behavior is if the object was created by placement new. Even then, calling the destructor will automatically call the destructor of every member and base class.
This is as it should be. Otherwise it would be very difficult to write a correct container class or memory manager.
The standard says that the lifetime of an object ends as soon as it enters the destructor. It does not become a base class object. It ceases to be an object, entirely. Also, if this was not the case, what would be the status of a class deriving from multiple bases after such a trick?
Ultimately, the "need" for such a functionality is a sign of bad design. I would guess your use case more likely requires composition. See if you can't solve it with a new class which holds one instance of what is currently the base class and one optional, replaceable component of (a smart pointer to) some dummy class which serves as an interface to and the new common base of your current derived classes. That way you can remove (and destruct) those sub objects without touching the base.
Destructors are called automatically in the reverse order of construction. I do not believe there is any way around this.
This is not possible to do unless your derived class has nothing to do with your base class.
Destructors are called in automatic way.Explicitly call destructor may result in undefined behavior.
Say we have a base class and a derived. So:
class base {
protected:
~base(){
//...
}
// ...
};
class derived : public base {
// ...
};
And now say that we have this code using the above classes with a smart pointer class:
SmartPointer<base> bptr(new derived());
delete bptr;
I understand that it would prevent slicing of the derived object by calling the destructor of derived, but how does it know to do that? Wouldn't the reference stored in the smart pointer be that of type base*? Does it traverse some kind of hierarchy tree, cast that pointer to derived* and then call delete? Or is there some other thing that I don't know about?
The implementation is supposedly threadsafe, non-intrusive, and reference counting.
YES, the classes that you see are akin to the ones that I'm testing against. There is apparently a way to do this with THESE GIVEN classes. The main idea as to how is mentioned in my question above, but I'm not sure as to how one such an implementation would work.
First thing is that as it stands the code will not work. The destructor of base must be at the very least protected (or derived classes be friends of the base). A private destructor means that the compiler will not allow you to write the destructor for the derived classes. Now, assuming that you have a protected destructor... (Rembember, if you design a class to be extended, provide either a public virtual destructor or a protected non-virtual!)
All depends on the implementation of the SmartPointer, in particular std::shared_ptr (or the boost counterpart boost::shared_ptr) are able to manage that situation cleanly. The solution performs some sort of partial type erasure of the type for destruction purposes. Basically, the smart pointer has a templated constructor that accepts any pointer that can be assigned to a base pointer, but because it is templated it knows the concrete type. At that point it stores a synthetic deleter function that will call the appropriate destructor.
For simplicity, using std::function:
template <typename T>
void delete_deleter( void * p ) {
delete static_cast<T*>(p);
}
template <typename T>
class shared_pointer {
T * ptr;
std::function<void(void*)> deleter;
public:
template <typename U>
shared_pointer( U* p, std::function<void()> d = delete_deleter<U> )
: ptr(p), deleter(d)
{}
~shared_pointer() {
deleter( ptr ); // call the stored destructor
}
};
The code is for exhibition only, it would have to be tweaked for production (where to store the function, reference counting...), but it is enough to give you the idea: in the only function where the exact type of the object is known (when creating the smart pointer), you create a wrapper that will call the exact version of the destructor that you need (providing some short of type erasure), then just leave it around and when you need to delete the object call it instead of the delete operator.
This can also be used to manage other resources that require calling a special method instead of delete:
// exhibition only!
shared_pointer<Foo> p( Factory.create(), &Factory::release );
Again there should be quite a lot of work before making this production ready.
Dependency on std::function which is used to simplify the erasure, can be eliminated from the problem. In the simple case (only memory allocated with new and freed with delete is supported in the smart pointer), then just provide a deleter base class with a single virtual operator()(void*), and then refactor the existing delete_deleter into templated derived classes from deleter that override operator()(void*) with the current implementation. If you need to go for the general case (hold any type of resource) it is not worth the effort, just use std::function or boost::function.
Well first of all, your destructor shouldn't be private or that won't compile at all. Secondly, if you're using a "smart pointer", you probably should not be deleting the pointer by hand at all (I don't know what implementation you're using though, but this strikes as odd to me).
Anyways if you're curious how the derived class' destructor gets called when the object is deleted through a pointer to the base class, the answer is polymorphism. But you're missing virtual declaration from your destructor, right now your code would not call the derived class' destructor.
How most C++ implementations implement this is through a virtual table.
If you using any of boost smart pointers or some other which is not friend of your Base class, then this code wouldn't compile, because destructor of Base class is protected (which is same as private for other independent from Base classes).
Now let's consider that you make SmartPointer<Base> friend of Base. This case the code will work, but it wouldn't call destructor of Derived but destructor of Base, because here your Base class is not polymorphic. You should declare destrucotr of Base as virtual. In last case the correct destructor will be called when your smart pointer is deleted.
this program is invalid.
1) the dtor of base is private
2) the dtor of base is not virtual
to answer your question: you need to correct #1 and #2. then the dtor will be called using dynamic dispatch (which will invoke each dtor in reverse order of construction).
without making those corrections, the only way SmartPointer could know to call derived's dtor in this example, and in a defined manner, is if SmartPointer was overly clever (or tedious to use).
Your base class desctructor needs to be virtual to ensure that destructor of derived class is called when deleting via base pointer.
Wikipedia entry on virtual desctructors
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 { ... };