For the smart pointer itself it depends on the smart pointer. A smart pointer to Derived
is not a class derived from that kind of smart pointer to Base
.
But you can cast the raw pointer. For that you have static_cast
if you know the pointee is of derived type, and dynamic_cast
for when you don't know (or just desire the checking) and the base class is polymorphic.
Note: Ownership assumptions can be broken if the raw pointer is downcasted and then used to construct a new smart pointer. For this case the original smart pointer's ownership should be released first. Usually that's a member function called release
.
For example:
#include <iostream>
#include <memory>
struct Base
{
int x;
};
struct Derived
: Base
{
void foo() const { std::cout << x << "\n"; }
Derived( int const value ): Base{ value } {}
};
auto main()
-> int
{
using std::unique_ptr;
unique_ptr<Base> p_base{ new Derived{ 42 } };
#ifdef CHECK
unique_ptr<Derived> p_directly_converted{ p_base }; // !Nyet
#endif
unique_ptr<Derived> p_derived{
static_cast<Derived*>( p_base.release() )
};
p_derived->foo();
}
std::unique_ptr
doesn't have an associated function that performs this downcast, so it must be done manually via either static_cast
or dynamic_cast
(for a polymorphic base), plus release
.
However, std::shared_ptr
has associated functions static_pointer_cast
, dynamic_pointer_cast
and const_pointer_cast
, and other smart pointers may have ditto functions – but this depends very much on the smart pointer.