Is there any difference between a protected and a private destructor in C++? If a base classes destructor is private, I imagine that it is still called when deleting the derived class object.
If the base class destructor is private or protected then you cannot call delete through the base-class pointer.
Use a protected destructor to prevent the destruction of a derived object via a base-class pointer. It limits access to the destuctor to derived classes. And it prevents automatic
(stack) objects of class base.
In effect it is used to allow any
other polymorphic use of derived
classes via pointers to base, but not
allow the users to delete using such a
pointer. Example:- Abstract Base Classes / Interfaces.
But a protected, non-virtual destructor on a non-final class seems to be a bug waiting to happen. Assuming you do not provide a destroy() function, you have to eventually make the dtor public. As soon as you do that, you have no further control over the class, and run the risk of polymorphic deletion with a non-virtual dtor, if someone derives further from your class.
Taken from here:
If the constructor/destructor is declared as private, then the class cannot be instantiated.
This is true, however it can be instantiated from another method in the class. Similarly, if the destructor is private, then the object can only be deleted from inside the class as well. Also, it prevents the class from being inherited (or at least, prevent the inherited class from being instantiated/destroyed at all).
The following piece of code will result in the compiler error (VC2010):
C2248: 'base::~base' : cannot access private member declared in class 'base'
class base
{
~base(){}
};
class derived : public base
{
};
int main ()
{
derived* d = new derived;
delete d;
}
However, if you change the base destructor to be protected, everything works fine.
The answer is that your assumption is wrong. The base class destructor cannot be called when it is private.
Related
I have a similar situation to this question where I have 2 classes that share a public interface function, and so I've pulled that function (manage_data_in_memory() in the example) out into a base class which the 2 classes inherit from. However, the 2 classes are otherwise not related, and one of them is polymorphic, whereas the other one isn't. It is also not expected for someone to declare an object of this base class, as it exists only to prevent code duplication (is there a way to enforce this? I know pure virtual functions can prevent an object from being instantiated, but declaring a dummy pure virtual that does nothing in the derived class seems like bad design).
Does the base class destructor need to be virtual in this case? This would force the other derived class to also have a virtual destructor, which it doesn't need.
Thanks.
So now I have code in the form
class base { // don't instantiate an object of this, is there a way to enforce this?
public:
void manage_data_in_memory();
protected:
data;
};
class derived : public base
{
public:
void sendData();
private:
virtual void sendDataHelper(); // override this in derived classes which need to send custom data in addition to the default data
};
class derived2 : public base
{
public:
void do_Z_On_data()
};
The destructor of a base class must be virtual if and only if an instance of a derived class will be destroyed through a pointer to the base object. If the destructor isn't virtual in such case, then the behaviour of the program would be undefined. Example:
struct Base {
// ...
};
struct Derived : Base {};
std::unique_ptr<Base> ptr = std::make_unique<Derived>();
// Base::~Base must be virtual
It's possible to prevent the user of the class from doing this (at least by accident) by using private inheritance. If the destructor isn't virtual, then inheritance should be private except possibly in special cases where you need a standard layout class.
is this because private inheritance would make the destructor private
No, private inheritance doesn't make destructor private.
which prevents anyone from declaring an object of Base?
No, and declaring an object of Base isn't a problem.
Private inheritance prevents conversion from derived pointer into a base pointer outside the member functions of the derived class (and friends). The inability acquire a pointer to base of the derived class would prevent the user from deleting a derived object through such pointer.
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);
As far as I understand the reason that we cannot pass a derived class object to a base class reference for private inheritance is that Since Derived is privately inherited from Base, the default constructor of Base would be called before the constructor of Derived. But because it is private and not inherited to Derived, we get a compiler error.
But, if I try to create a public constructor for Base and inherit from Derived privately and then re-assign the public status to Base's constructor will it allow me to pass a derived's instance to Base reference?
I tried it as follows,
#include <iostream>
using namespace std;
class base
{
public:
base(){}
void print(){ puts("In base"); }
};
class derived : private base
{
public:
base::base; /* Throws an error - Declaration doesnt declare anything*/
void print(){ puts("In derived"); }
};
void func(base& bRef)
{
}
int main()
{
derived dObj;
func(dObj); /* Throws an error - 'base' is an inaccessible base of derived */
}
It throws an error for base::base (publicizing privately inherited constructor to public).
Is what I am trying valid? Can anyone please tell me?
The reason we cannot have a base class reference to a derived object that inherits privately is because that would violate the Liskov Substitution Principle: the derived object IS-NOT-A base class object because it does not provide the base class public interface. You cannot work around this
For this reason, private inheritance is a way of reusing implementation and not when you want to make a more specialized type. As this can most of the time be done with composition (i.e. having a member of the base class instead of privately deriving), private inheritance might be a bad code smell.
You can read here (be sure to follow all the links) for more information on when private inheritance is a good option (summary: when there simply is no other choice).
No, it is not valid to point to an object of Derived with a pointer or reference of Base class. If it were possible, then the whole purpose of private inheritance (hide the fact that the derived class inherits part (or the whole) of its functionality from the base class) would be useless.
Say you have a method foo() in the base class. You don't want this method to be called. But if it were possible to point the object from a pointer of the base class, then it would also be possible to call foo().
Base * ptrBase = &objDerived; // Let's suppose this would compile
ptrBase->foo(); // Now we can call foo() (?)
When you declare private inheritance, is as if the Derived class where not related to the base class. It is just you, the developer, the only one that should "know" that this relationship exist, and actually you should forget about it, because it just won't work.
Private inheritance is just there solely as a reusability mechanism, not as a true inheritance mechanism. It is not recommended to even use it, since you can obtain a better result by simply applying composition (i.e. just make an attribute of class Base in Derived).
This question already has answers here:
Do I need to explicitly call the base virtual destructor?
(7 answers)
Closed 7 years ago.
Please consider the following:
class base{
base();
~base();
}:
class derived : public base{
};
Does a base class destructor get automatically invoked when a derived object is destructed when the derived class has no destructor defined?
Otherwise, if I DO have a destructor in the derived class too, do I have to call the base class destructor explicitly?
class base{
base();
~base();
}:
class derived : public base{
derived();
~derived{
base::~base(); //do I need this?
}
};
The base class destructor is automatically invoked in this case; you do not need to call it.
However, note that when destroying an object through delete on a base class pointer and the destructor is not virtual, the result is going to be undefined behavior (although you might not get a crash).
Always declare the destructor as virtual in any class which is meant to be derived from. If the base class does not need to have a destructor, include a virtual one anyway with an empty body.
There is an exception to the above rule for an edge case: if your derived classes do not need to support polymorphic destruction, then the destructor does not need to be virtual. In this case it would be correct to make it protected instead; more details here, but be advised that this rarely occurs in practice.
Does a base class destructor is automatically invoked when a derived object is destructed and the derived class has no destructor defined?
Yes, the Base class destructor is automatically invoked after the Derived class Destructor, irrespective of Derived class destructor being explicitly defined or not.
Otherwise, if I have a destructor in the derived class too, do I need to call explicitly base class destructor too?
No, You don't need to.
There will not be any scenario in C++, where one has to explicitly invoke a destructor except while using placement new.
No, base destructors are invoked automatically in this case, in much the same way that base constructors are can be invoked automatically.
Note, though, that if you are using polymorphism and destroying through a base pointer, you should make sure that the destructor is virtual otherwise this will break.
You should never invoke a base class destructor from a derived class destructor.
The reason is base class destructor will be then called automatically for the second time and writing destructors in such way that this doesn't cause problem is problematic - see this question.
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 { ... };