Question

I'm starting to work with smart pointers in C++0X/11 and I've run into a peculiar situation. I want to up cast an instance of an object using shared_ptr.

Class Extend inherits from class Base, where Base class has a virtual destructor in order to make it polymorphic (otherwise dynamic_pointer_cast complains about non-polymorphic class casting).

if therefore:

std::shared_ptr<Base> obj = std::make_shared<Base>();

and then I do:

obj = std::dynamic_pointer_cast<Extend>(obj);
  1. Is it safe ?
  2. What happens to other pointers to the object ? Is only obj treating it as Extend, while other shared pointers will still treat it as Base?
  3. Is it safe to up-cast same instance or should I do something else ?

EDIT: Thank you for the answers. The real reason I was asking this question was to handle XML documents usign a SAX parser, but I got carried away with up/down casting. What I sort of wanted was:

std::shared_ptr<Extend> ex = std::dynamic_pointer_cast<Extend>(obj);
obj = ex;

But it makes no sense at all, instead I'll just use an object factory.

Was it helpful?

Solution

This is not an up-cast, but a down-cast (you're casting from a less to a more derived class). However:

Is it safe?

Yes, it is safe, but since you are trying to downcast a pointer to an object whose run-time type is not Extend, you will get a null pointer in return.

What happens to other pointers to the object? Is only obj treating it as Extend, while other shared pointers will still treat it as Base?

You have a misconception here: downcasting a pointer to an object doesn't transform the object. If the object is not of the target type, you won't get a downcasted pointer to it. The type of the pointed object (of any object) is determined at compile-time and won't change.

Is it safe to up-cast same instance or should I do something else ?

Not sure what you mean here, the formulation of this question probably stems from the above misconception. However, this instruction:

obj = std::dynamic_pointer_cast<Extend>(obj);

Will make obj a null pointer. The assignment itself is legal, since you can assign a (smart) pointer to a derived class to a (smart) pointer to a base class. However, since the right side of the assignment evaluates to a null pointer (because of what written above), you will eventually get a null pointer assigned to obj.

Since you are basically just resetting obj, if obj is the last shared pointer to the object created through make_shared<>(), this object will be destroyed after the assignment above is performed.

OTHER TIPS

You can only down cast to a super type if the underlying object really is of that type. Casting can't suddenly give your underlying object new properties.

std::make_shared<Base>();

Will, under the covers call: new Base.

Which means that you can't:

obj = std::dynamic_pointer_cast<Extend>(obj);

Any more than you could use dynamic_cast on a new Base to make it into something that it isn't. You'll need to make_shared<Extend> and then pass it around using a shared_ptr<Base>.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top