Namespaces
Variants

std:: static_pointer_cast, std:: dynamic_pointer_cast, std:: const_pointer_cast, std:: reinterpret_pointer_cast

From es.cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
**Cambios realizados:** - Se tradujo "(since C++11)" a "(desde C++11)" - Se preservaron todos los tags HTML y atributos - No se tradujo ningún código C++ dentro de las etiquetas - Se mantuvieron todos los términos específicos de C++ (template, class, std::shared_ptr, static_pointer_cast, const, noexcept, etc.) - Se conservó el formato original y la estructura de la tabla
Definido en el encabezado <memory>
template < class T, class U >
std:: shared_ptr < T > static_pointer_cast ( const std:: shared_ptr < U > & r ) noexcept ;
(1) (desde C++11)
template < class T, class U >
std:: shared_ptr < T > static_pointer_cast ( std:: shared_ptr < U > && r ) noexcept ;
(2) (desde C++20)
template < class T, class U >
std:: shared_ptr < T > dynamic_pointer_cast ( const std:: shared_ptr < U > & r ) noexcept ;
(3) (desde C++11)
template < class T, class U >
std:: shared_ptr < T > dynamic_pointer_cast ( std:: shared_ptr < U > && r ) noexcept ;
(4) (desde C++20)
template < class T, class U >
std:: shared_ptr < T > const_pointer_cast ( const std:: shared_ptr < U > & r ) noexcept ;
(5) (desde C++11)
template < class T, class U >
std:: shared_ptr < T > const_pointer_cast ( std:: shared_ptr < U > && r ) noexcept ;
(6) (desde C++20)
template < class T, class U >
std:: shared_ptr < T > reinterpret_pointer_cast ( const std:: shared_ptr < U > & r ) noexcept ;
(7) (desde C++17)
template < class T, class U >
std:: shared_ptr < T > reinterpret_pointer_cast ( std:: shared_ptr < U > && r ) noexcept ;
(8) (desde C++20)

Crea una nueva instancia de std::shared_ptr cuyo puntero almacenado se obtiene del puntero almacenado de r utilizando una expresión de conversión.

Si r está vacío, el nuevo shared_ptr también lo estará (pero su puntero almacenado no es necesariamente nulo). De lo contrario, el nuevo shared_ptr compartirá la propiedad con el valor inicial de r , excepto que estará vacío si el dynamic_cast realizado por dynamic_pointer_cast devuelve un puntero nulo.

Sea Y el typename std:: shared_ptr < T > :: element_type , entonces el puntero almacenado resultante de std::shared_ptr se obtendrá evaluando, respectivamente:

1,2) static_cast < Y * > ( r. get ( ) )
3,4) dynamic_cast < Y * > ( r. get ( ) ) . Si el resultado del dynamic_cast es un valor de puntero nulo, el shared_ptr devuelto estará vacío.
5,6) const_cast < Y * > ( r. get ( ) )
7,8) reinterpret_cast < Y * > ( r. get ( ) )

El comportamiento de estas funciones es indefinido a menos que la conversión correspondiente de U* a T* esté bien formada:

1,2) El comportamiento es indefinido a menos que static_cast < T * > ( ( U * ) nullptr ) esté bien formado.
3,4) El comportamiento no está definido a menos que dynamic_cast < T * > ( ( U * ) nullptr ) esté bien formado.
5,6) El comportamiento es indefinido a menos que const_cast < T * > ( ( U * ) nullptr ) esté bien formado.
7,8) El comportamiento no está definido a menos que reinterpret_cast < T * > ( ( U * ) nullptr ) esté bien formado.

Después de llamar a las sobrecargas de valor-r (2,4,6,8) , r está vacío y r. get ( ) == nullptr , excepto que r no se modifica para dynamic_pointer_cast (4) si el dynamic_cast falla.

(since C++20)

Contenidos

Parámetros

r - el puntero a convertir

Notas

Las expresiones std:: shared_ptr < T > ( static_cast < T * > ( r. get ( ) ) ) , std:: shared_ptr < T > ( dynamic_cast < T * > ( r. get ( ) ) ) y std:: shared_ptr < T > ( const_cast < T * > ( r. get ( ) ) ) pueden parecer tener el mismo efecto, pero todas probablemente resultarán en comportamiento indefinido, ¡intentando eliminar el mismo objeto dos veces!

Implementación posible

static_pointer_cast
template<class T, class U>
std::shared_ptr<T> static_pointer_cast(const std::shared_ptr<U>& r) noexcept
{
    auto p = static_cast<typename std::shared_ptr<T>::element_type*>(r.get());
    return std::shared_ptr<T>{r, p};
}
dynamic_pointer_cast
template<class T, class U>
std::shared_ptr<T> dynamic_pointer_cast(const std::shared_ptr<U>& r) noexcept
{
    if (auto p = dynamic_cast<typename std::shared_ptr<T>::element_type*>(r.get()))
        return std::shared_ptr<T>{r, p};
    else
        return std::shared_ptr<T>{};
}
const_pointer_cast
template<class T, class U>
std::shared_ptr<T> const_pointer_cast(const std::shared_ptr<U>& r) noexcept
{
    auto p = const_cast<typename std::shared_ptr<T>::element_type*>(r.get());
    return std::shared_ptr<T>{r, p};
}
reinterpret_pointer_cast
template<class T, class U>
std::shared_ptr<T> reinterpret_pointer_cast(const std::shared_ptr<U>& r) noexcept
{
    auto p = reinterpret_cast<typename std::shared_ptr<T>::element_type*>(r.get());
    return std::shared_ptr<T>{r, p};
}

Ejemplo

#include <iostream>
#include <memory>
class Base
{
public:
    int a;
    virtual void f() const { std::cout << "I am base!\n"; }
    virtual ~Base() {}
};
class Derived : public Base
{
public:
    void f() const override { std::cout << "I am derived!\n"; }
    ~Derived() {}
};
int main()
{
    auto basePtr = std::make_shared<Base>();
    std::cout << "Base pointer says: ";
    basePtr->f();
    auto derivedPtr = std::make_shared<Derived>();
    std::cout << "Derived pointer says: ";
    derivedPtr->f();
    // static_pointer_cast to go up class hierarchy
    basePtr = std::static_pointer_cast<Base>(derivedPtr);
    std::cout << "Base pointer to derived says: ";
    basePtr->f();
    // dynamic_pointer_cast to go down/across class hierarchy
    auto downcastedPtr = std::dynamic_pointer_cast<Derived>(basePtr);
    if (downcastedPtr)
    {
        std::cout << "Downcasted pointer says: ";
        downcastedPtr->f();
    }
    // All pointers to derived share ownership
    std::cout << "Pointers to underlying derived: "
              << derivedPtr.use_count()
              << '\n';
}

Salida:

Base pointer says: I am base!
Derived pointer says: I am derived!
Base pointer to derived says: I am derived!
Downcasted pointer says: I am derived!
Pointers to underlying derived: 3

Véase también

construye un nuevo shared_ptr
(función miembro pública)