Click to See Complete Forum and Search --> : Protected Virtual destructors Q.


Metro_Mystery
May 13th, 2008, 05:28 AM
I'm aware of the common problem...



class A {
public:
A();
~A();

virtual void x();
};

class B: public A {
public:
B();
~B();

virtual void x();
};

A* pA = new B;
delete pA; //~B() never called;



Lets say B should not have been virtual & derived from; but it happened anyway.

Someone told me that declaring the destructor for A protected prevents inheritance at compile time... but wouldn't that disallow the object to be created altogether?

I'm a bit confused, could someone please shed some light on this?

Thanks

laserlight
May 13th, 2008, 05:32 AM
Someone told me that declaring the destructor for A protected prevents inheritance at compile time... but wouldn't that disallow the object to be created altogether?
It does not prevent inheritance but it does prevent the creation of objects of type A.

Metro_Mystery
May 13th, 2008, 05:36 AM
Thanks for the response.

In that case... is there any "simple" way to prevent people deriving classes from object A?

barbuceanu
May 13th, 2008, 05:39 AM
As far as I know, If you declare a constructor protected you won't be able to instantiate that class directly with the constructor, but you will be able to instantiate a class derived from that one directly with the constructor.

I other words, if the constructor is protected this means it is not for public access, unless for a derived class. So it's like it is private, and if it is private you can't create objects directly with the constructor. To create an object of that class you should use a public method from that class which will call the constructor.

Home this makes sense for you.

laserlight
May 13th, 2008, 05:48 AM
In that case... is there any "simple" way to prevent people deriving classes from object A?
Read Stroustrup's answer to the FAQ: Can I stop people deriving from my class? (http://www.research.att.com/~bs/bs_faq2.html#no-derivation)

TheCPUWizard
May 13th, 2008, 06:16 AM
Stroustrup's answer is (of course :) ) the correct one.

But if you are willing to make your user utilize a factory method to create the object then private constructors will do the trick.

This DOES impose some significant real-worl limitations on how the class can be used, but if utilized consistantly it can form the basis for a robust design.

As an example, if you allow users to create instances either automatically or via calles to new, then it can be difficult (if not impossible) to implement many DI (dependancy injection) patterns. Forcing users to always you a factory provides the basis for making that factory dynamic.

Graham
May 13th, 2008, 06:45 AM
I had to look this up, so I thought I'd just share a point regarding the Stroustrup solution above. This is for the benefit of those who don't already know this:

The reason why Usable_lock has to be a virtual base class of Usable is this statement from the Standard:

All sub-objects representing virtual base classes are initialized by the constructor of the most derived class.

This means that, under "normal" circumstances, Usable is the most derived class and is responsible for initialising Usable_lock. This is OK, since Usable is a friend of Usable_lock. When we try to derive from Usable, however, this new class becomes the most derived and is responsible for initialising Usable_lock - something it can't do, because it's not a friend.

If Usable did not inherit virtually from Usable_lock, then it would always be responsible for initialising it, so the trick wouldn't work.

Ajay Vijay
May 13th, 2008, 12:26 PM
"Declaring a private destructor." would be the answer to:

"How to prevent stack allocation of my class?"

Zeeshan
May 13th, 2008, 01:09 PM
"Declaring a private destructor." would be the answer to:

"How to prevent stack allocation of my class?"

Not exactly you can still create a object of a class with private destructor on stack with the help of friend class. Take a look at this example, here even constructor is also private.


class FriendClass;

class PrivateDtor
{
private:
PrivateDtor()
{
std::cout << "PrivateDtor::PrivateDtor" << std::endl;
}

~PrivateDtor()
{
std::cout << "PrivateDtor::~PrivateDtor" << std::endl;
}
friend class FriendClass;
};

class FriendClass
{
private:
PrivateDtor m_objPrivateDtor;
};

Ajay Vijay
May 13th, 2008, 01:12 PM
Well, the class itself is assigning "rights" to other class (or function).

What I explained was "denying" everyone to create stack instance.

Zeeshan
May 13th, 2008, 01:27 PM
Well, the class itself is assigning "rights" to other class (or function).

What I explained was "denying" everyone to create stack instance.

You are absolutely right. I just wanted to show how it is possible using friend classes i.e. "denying everyone other than friends". There is even one non-standard way too, you can compile this code in even VC 2008, but again it is non-standard.


template <typename T>
class PrivateDtor
{
private:
PrivateDtor()
{
std::cout << "PrivateDtor::PrivateDtor" << std::endl;
}

~PrivateDtor()
{
std::cout << "PrivateDtor::~PrivateDtor" << std::endl;
}
friend typename T;
};

class FriendClass
{
private:
PrivateDtor<FriendClass> m_objPrivateDtor;
};



Here "friend typename T;" is a non standard way.

TheCPUWizard
May 13th, 2008, 05:34 PM
"Declaring a private destructor." would be the answer to:

"How to prevent stack allocation of my class?"


OF course this means that when you new and object onto the heap, you can NOT delete it, and a forcing a memory leak....

ps: For those interested, read Scott Meyer's "Effective C++" for a good explanation of why it is IMPOSSIBLE to create usuable objects that are forced to either the stack or the heap.