考慮してください:
_struct SomethingThatsABase
{
virtual bool IsChildOne() const { return false; }
virtual bool IsChildTwo() const { return false; }
};
struct ChildOne : public SomethingThatsABase
{
virtual bool IsChildOne() const { return true; }
};
struct ChildTwo : public SomethingThatsABase
{
virtual bool IsChildTwo() const { return true; }
};
void SomeClientExpectingAChildOne(std::shared_ptr<ChildOne> const& ptrOne)
{
//Does stuff
}
void SomeClient(std::shared_ptr<SomethingThatsABase> const& ptr)
{
if (ptr->IsChildOne())
{
SomeClientExpectingAChildOne(ptr); //Oops.
//Hmm.. can't static_cast here, because we need a `shared_ptr` out of it.
}
}
_
(参照カウントが2つの_shared_ptr
_ s間で共有されないため、単純にstd::shared_ptr<ChildOne>(static_cast<ChildOne*>(ptr.get()))
を実行できないことに注意してください)
これは動作するはずです:
if (ptr->IsChildOne())
{
SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr));
}
shared_ptr
に相当するstatic_cast
はstatic_pointer_cast
、 そしてその shared_ptr
に相当するdynamic_cast
はdynamic_pointer_cast
。
C++ 11以降、C++標準の§20.10.2.2.9( [util.smartptr.shared.cast] )は、 _static_cast
_、_const_cast
_、および_dynamic_cast
_の場合、_std::shared_ptr
_は次のようになります。
std::static_pointer_cast
_:_template <class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
_
_static_pointer_cast
_には、static_cast<T *>(r.get())
の整形式が必要です。 r
が空の場合は、空の_shared_ptr<T>
_が返されます。そうでない場合は、w
(w.get() == static_cast<T *>(r.get())
およびw.use_count() == r.use_count()
)と所有権を共有するポインターr
が返されます。
std::const_pointer_cast
_:_template <class T, class U>
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;
_
_const_pointer_cast
_には、_static_pointer_cast
_の代わりに_const_cast
_が使用されることを除いて、_static_cast
_と同様の要件とセマンティクスがあります。
std::dynamic_pointer_cast
_:_template <class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;
_
_dynamic_pointer_cast
_は、dynamic_cast<T *>(r.get())
の形式が適切であり、セマンティクスが明確に定義されている必要があるため、少し異なります。 dynamic_cast<T *>(r.get())
がゼロ以外の値である場合、所有権をw
と共有するポインターr
を返します。ここでw.get() == dynamic_cast<T *>(r.get())
およびw.use_count() == r.use_count()
、そうでない場合は空の_shared_ptr<T>
_が返されます。
std::reinterpret_pointer_cast
_:C++ 17の場合、 N3920 (2014年2月にLibrary Fundamentals TS に採用されました )上記と同様の_std::reinterpret_pointer_cast
_も提案しました。これは、reinterpret_cast<T *>((U *) 0)
が整形式である必要があるだけで、shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type *>(r.get()))
を返します。注N3920は、他の_shared_ptr
_キャストの表現を変更し、配列をサポートするように_shared_ptr
_を拡張しました。