Downcasting shared_ptr<Base> to shared_ptr<Derived>?
You can use dynamic_pointer_cast
. It is supported by std::shared_ptr
.
std::shared_ptr<Base> base (new Derived());
std::shared_ptr<Derived> derived =
std::dynamic_pointer_cast<Derived> (base);
Documentation: https://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast
Also, I don't recommend using cast operator in the base class. Implicit casting like this may become the source of bugs and errors.
-Update: If the type is not polymorphic, std::static_pointer_cast
may be used.
I assume you're using boost::shared_ptr
... I think you want dynamic_pointer_cast
or shared_polymorphic_downcast
.
However, these require polymorphic types.
what kind of type
Base* const
is?const Base*
I understand, butBase* const
? What doesconst
refer to in this case?
-
const Base *
is a mutable pointer to a constantBase
. -
Base const *
is a mutable pointer to a constantBase
. -
Base * const
is a constant pointer to a mutableBase
. -
Base const * const
is a constant pointer to a constantBase
.
Here's a minimal example:
struct Base { virtual ~Base() { } }; // dynamic casts require polymorphic types
struct Derived : public Base { };
boost::shared_ptr<Base> base(new Base());
boost::shared_ptr<Derived> derived;
derived = boost::static_pointer_cast<Derived>(base);
derived = boost::dynamic_pointer_cast<Derived>(base);
derived = boost::shared_polymorphic_downcast<Derived>(base);
I'm not sure if it was intentional that your example creates an instance of the base type and casts it, but it serves to illustrate the difference nicely.
The static_pointer_cast
will "just do it". This will result in undefined behavior (a Derived*
pointing at memory allocated for and initialized by Base
) and will likely cause a crash, or worse. The reference count on base
will be incremented.
The dynamic_pointer_cast
will result in a null pointer. The reference count on base
will be unchanged.
The shared_polymorphic_downcast
will have the same result as a static cast, but will trigger an assertion, rather than seeming to succeed and leading to undefined behavior. The reference count on base
will be incremented.
See (dead link):
Sometimes it is a little hard to decide whether to use
static_cast
ordynamic_cast
, and you wish you could have a little bit of both worlds. It is well known that dynamic_cast has a runtime overhead, but it is safer, whereas static_cast has no overhead at all, but it may fail silently. How nice it would be if you could useshared_dynamic_cast
in debug builds, andshared_static_cast
in release builds. Well, such a thing is already available and is calledshared_polymorphic_downcast
.
If somebody gets here with boost::shared_ptr...
This is how you can downcast to the derived Boost shared_ptr. Assuming Derived inherits from Base.
boost::shared_ptr<Base> bS;
bS.reset(new Derived());
boost::shared_ptr<Derived> dS = boost::dynamic_pointer_cast<Derived,Base>(bS);
std::cout << "DerivedSPtr is: " << std::boolalpha << (dS.get() != 0) << std::endl;
Make sure 'Base' class/struct has at least one virtual function. A virtual destructor also works.