Using static_pointer_cast<T>(..) and dynamic_pointer_cast<T>(..)
This demonstrates how to use static_pointer_cast<T>(..) and dynamic_pointer_cast<T>(..). It is like the previous post which shows how to use const_pointer_cast<T>(..).
First the headers and some class declarations:
# include <boost/assert.hpp>
# include <boost/pointer_cast.hpp>
# include <boost/shared_ptr.hpp>
using boost::shared_ptr;
using boost::static_pointer_cast;
using boost::dynamic_pointer_cast;
class
base_type
{ public: virtual ~base_type( ) { } };
class
derived_type
: public base_type
{ };
class
derived_type_other
: public base_type
{ };
Notice base_type has a virtual destructor, which makes it a polymorphic class. A class has to have at least one virtual method if you want to use it with dynamic_pointer_cast<T>(..). Otherwise the compiler complains loudly.
Remember that, in general, declaring the destructors virtual is often not necessary if a class is being managed by shared_ptr<T>. If you always immediately attach a new target object to a shared_ptr< MOST_DERIVED_CLASS > after creation, then you don’t have to worry if shared_ptr< BASE_CLASS > later deletes that target object. The most-derived destructor is bound to the shared_ptr<T> during first attach and is passed along to subsequent shared and weak pointers.
Finally, here is the code showing static_pointer_cast<T>(..) and dynamic_pointer_cast<T>(..).
// Make a shared_ptr to a new object. shared_ptr< derived_type > sp_derived( new derived_type); // The shared_ptr knows how to upcast its // inner pointer. shared_ptr< base_type > sp_base( sp_derived); // You can static-downcast the inner pointer. shared_ptr< derived_type > sp_derived2( static_pointer_cast< derived_type >( sp_base)); // You can dynamic-downcast the inner pointer // as long as the inner type is polymorphic. shared_ptr< derived_type > sp_derived3( dynamic_pointer_cast< derived_type >( sp_base)); BOOST_ASSERT( sp_derived3); // You can try to dynamic-downcast to the wrong type. // You will end up with a null shared_ptr because // the inner dynamic-downcast returns a zero pointer. // This does not throw std::bad_cast because it casts // pointers and not refs. shared_ptr< derived_type_other > sp_derived_other( dynamic_pointer_cast< derived_type_other >( sp_base)); BOOST_ASSERT( ! sp_derived_other);
Like const_pointer_cast<T>(..), static_pointer_cast<T>(..) and dynamic_pointer_cast<T>(..) also work with intrusive_ptr<T>s and raw pointers. But they don’t work with weak_ptr<T>, at least not in Boost 1_37_0 (I suspect it’s an oversight). They also do not work with shared_array<T>, which makes sense since array “pointers” should always be to the most-derived type, and of course they don’t work with the single-ownership smart pointers that don’t support normal copy semantics.
There is also a reinterpret_pointer_cast<T>(..) function, but it only works with raw pointers. Reinterpret cast is usually only used at a very low abstraction level, while smart pointers are highly abstracted. If you think you need a reinterpret cast with a smart pointer you are probably doing something wrong.
Comments
Leave a Reply