Per my previous question, I wish that a boost::shared_ptr<A>
was actually a subclass of A
(or perhaps A*
) so that it could be used in methods that took A*
as their argument.
Consider the following class:
class A
{
public:
A(int x) {mX = x;}
virtual void setX(int x) {mX = x;}
virtual int getX() const {return mX;}
private:
int mX;
};
In the previous question, I proposed the creation of a SharedA object to take care of this, and presumably it does.
class SharedA : public A
{
public:
SharedA(A* a) : mImpl(a){}
virtual void setX(int x) {mImpl->setX(x);}
virtual int getX() const {return mImpl->getX();}
private:
boost::shared_ptr<A> mImpl;
};
It would be Grrrrrrrreat thought, if I could create a template class to take care of all of this for me.
template <class T>
class Shared : public T
{
public:
SharedT(T* t) : mImpl(t)
{
//What kind of crazy voodoo goes here?
}
private:
boost::shared_ptr<T> mImpl;
};
If I had this, (along with the proper constructors in Shared<T>
), then I could do the following:
A* indestructo_A = new Shared<A>(new A(100));
A* indestructo_A_clone = new Shared<A>(indestructo_A);
delete indestructo_A
cout << "Indestructo-A back with a vengence!" << indestructo_A_clone.getX();
Questions:
Is this useful? Or is its utility only in corner cases where you're dealing with particularly bad code. For instance:
void aFunctionYouHaveToUse(A* a)
{
/some useful algorithm and then/
delete a;
}
Is it possible to build such a templated class? (I guess you need reflection, right?) If you can build it, how?
There's a really, darn good reason why shared_ptr does not allow explicit casting to A* (there are better ways of doing it than inheriting, which would be impossible anyway). The whole purpose of shared_ptr, and other smart pointers, are to provide a small, encapsulated object that's sole purpose is to own a pointer and to decide when and how to delete it.
If this object allowed that same pointer to just get passed around wily-nily, without thought, then it simply could not serve its purpose. Any time you dig into a smart pointer to get at the raw pointer inside you violate its ownership semantics and must then take very careful care not to go doing something stupid. Smart pointers make you think about this by forcing you to make a call to get at the pointer inside rather than just silently doing so whenever you accidentally pass it to the wrong kind of function. Think of it like the smart pointer saying, "Hey, you know what you're doing can be dangerous, right? OK then, here you go."
IMHO, the universe would be a better place if shared pointers didn't allow access to their pointers. Unfortunately, that's not this universe and can't be this universe because occasionally you still need to pass that thing into a function that doesn't use smart pointers. So, since we don't live in that better universe, OUR smart pointers do allow access, they're just not sluts about it.