Considérer:
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.
}
}
(Notez que je ne peux pas simplement faire une std::shared_ptr<ChildOne>(static_cast<ChildOne*>(ptr.get()))
, car alors le nombre de références n'est pas partagé entre les deux shared_ptr
S)
Cela devrait fonctionner:
if (ptr->IsChildOne())
{
SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr));
}
Le shared_ptr
équivalent de static_cast
est static_pointer_cast
, et le shared_ptr
équivalent de dynamic_cast
est dynamic_pointer_cast
.
À partir de C++ 11, le §20.10.2.2.9 ( [util.smartptr.shared.cast] ) de la norme C++ spécifie les équivalents de static_cast
, const_cast
et dynamic_cast
pour que std::shared_ptr
soit comme suit:
std::static_pointer_cast
:template <class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
static_pointer_cast
Nécessite que static_cast<T *>(r.get())
soit bien formé. Si r
est vide, un shared_ptr<T>
Est renvoyé, sinon renvoie un pointeur w
partageant la propriété avec r
où w.get() == static_cast<T *>(r.get())
et 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
A des exigences et une sémantique similaires à static_pointer_cast
, Sauf que const_cast
Est utilisé à la place de 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
Est un peu différent car il nécessite que dynamic_cast<T *>(r.get())
soit bien formé et ait une sémantique bien définie. Si dynamic_cast<T *>(r.get())
est une valeur non nulle, renvoie un pointeur w
partageant la propriété avec r
où w.get() == dynamic_cast<T *>(r.get())
et w.use_count() == r.use_count()
, sinon un shared_ptr<T>
vide est retourné.
std::reinterpret_pointer_cast
:Pour C++ 17, N392 (adopté dans Library Fundamentals TS en février 2014 ) a également proposé un std::reinterpret_pointer_cast
Similaire au précédent, qui ne nécessiterait que reinterpret_cast<T *>((U *) 0)
pour être bien formé et renvoie shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type *>(r.get()))
. Remarque N3920 a également modifié le libellé des autres transtypages shared_ptr
Et étendu shared_ptr
Pour prendre en charge les tableaux.