考虑:
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.
}
}
(请注意,我不能简单地执行std::shared_ptr<ChildOne>(static_cast<ChildOne*>(ptr.get()))
,因为之后引用计数不会在两个shared_ptr
之间共享
答案 0 :(得分:81)
这应该有效:
if (ptr->IsChildOne())
{
SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr));
}
答案 1 :(得分:34)
shared_ptr
等效static_cast
为static_pointer_cast
,而shared_ptr
等效dynamic_cast
为dynamic_pointer_cast
。
答案 2 :(得分:19)
从C ++ 11开始,C ++标准的§20.10.2.2.9([util.smartptr.shared.cast])指定了static_cast
,const_cast
和dynamic_cast
的等价物{ {1}}如下:
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>
与[{1}}共享所有权w
和r
。< / p>
w.get() == static_cast<T *>(r.get())
w.use_count() == r.use_count()
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())
与[{1}}共享所有权dynamic_cast<T *>(r.get())
和w
,否则为空r
归还。
w.get() == dynamic_cast<T *>(r.get())
对于C ++ 17,N3920(已在图书馆基础知识TS in February 2014中采用)也提出了与上述类似的w.use_count() == r.use_count()
,只需要shared_ptr<T>
格式良好并返回std::reinterpret_pointer_cast
。注意N3920还更改了其他std::reinterpret_pointer_cast
强制转换和扩展reinterpret_cast<T *>((U *) 0)
的措辞以支持数组。