Just in case it wasn't clear from juanchopanza's answer, this line
std::shared_ptr<A> (static_cast<A*>(objectB.get()));
is incorrect and leads to undefined behavior.
The shared pointer you construct here just takes the pointer you give it. It has no idea that the object pointed to by that pointer is already owned by another smart pointer. Furthermore it doesn't know that the pointer points to a sub-object and that the pointer will need to be cast back to B*
in order to be delete
d, because the static_cast
hides that information from it.
To cast smart pointers you need a cast that understands and is integrated with smart pointers. C++ has std::static_pointer_cast
and std::dynamic_pointer_cast
for this purpose.
int main() {
std::shared_ptr<B> objectB(new B());
{
std::shared_ptr<A> x = std::static_pointer_cast<A>(objectB);
std::cout << "End of inner scope\n";
}
std::cout << "End of outer scope\n";
}
With this code the output of your program shows correct behavior:
make A
make B
End of inner scope
End of outer scope
~B
~A
Of course in this particular case you don't need an explicit cast, because std::shared_ptr
can figure out legal up-casts and do them implicitly. You need std::static_pointer_cast
to do down-casts though:
int main() {
std::shared_ptr<A> objectA(new B());
{
std::shared_ptr<B> x = std::static_pointer_cast<B>(objectA);
std::cout << "End of inner scope\n";
}
std::cout << "End of outer scope\n";
}
Thanks, one last thing, if I don't need objectB, is it safe to do std::shared_ptr<A> objectA(new B());
?
Yes, this does happen to be safe. The shared_ptr<A>
constructor receives a B*
and knows enough to store the fact that when deletion occurs it will need to convert the A*
that it holds to B*
. This ensures that the object gets deleted correctly.
However, if you really want your types A
and B
to behave polymorphically then you should probably just make them polymorphic types by adding virtual destructors, and then you don't have to worry about how smart std::shared_ptr
is about this.