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

< cpp‎ | memory‎ | shared ptr

定义于头文件 `<memory>` |  |
template< class T, class U > std::shared_ptr<T> static_pointer_cast( const std::shared_ptr<U>& r ) noexcept; | (1) | (C++11 起)
template< class T, class U > std::shared_ptr<T> static_pointer_cast( std::shared_ptr<U>&& r ) noexcept; | (2) | (C++20 起)
template< class T, class U > std::shared_ptr<T> dynamic_pointer_cast( const std::shared_ptr<U>& r ) noexcept; | (3) | (C++11 起)
template< class T, class U > std::shared_ptr<T> dynamic_pointer_cast( std::shared_ptr<U>&& r ) noexcept; | (4) | (C++20 起)
template< class T, class U > std::shared_ptr<T> const_pointer_cast( const std::shared_ptr<U>& r ) noexcept; | (5) | (C++11 起)
template< class T, class U > std::shared_ptr<T> const_pointer_cast( std::shared_ptr<U>&& r ) noexcept; | (6) | (C++20 起)
template< class T, class U > std::shared_ptr<T> reinterpret_pointer_cast( const std::shared_ptr<U>& r ) noexcept; | (7) | (C++17 起)
template< class T, class U > std::shared_ptr<T> reinterpret_pointer_cast( std::shared_ptr<U>&& r ) noexcept; | (8) | (C++20 起)

创建 std::shared_ptr 的新实例，其存储指针从 `r` 的存储指针用转型表达式获得。

若 `r` 为空，则新的 `shared_ptr` 亦然（但其存储指针不必为空）。否则，新的 `shared_ptr` 将与 `r` 的初始值共享所有权，除了若 `dynamic_pointer_cast` 所进行的 `dynamic_cast` 返回空指针，则为它空。

令 `Y` 为 typename std::shared_ptr<T>::element_type ，则将分别通过求值下列表达式，获得生成 std::shared_ptr 的存储指针：

1-2) static_cast<Y*>(r.get()) 。
3-4) dynamic_cast<Y*>(r.get()) （若 `dynamic_cast` 的结果是空指针值，则返回的 `shared_ptr` 将为空）。
5-6) const_cast<Y*>(r.get()) 。
7-8) reinterpret_cast<Y*>(r.get()) 。

这些函数的行为未定义，除非从 `U*` 到 `T*` 的对应转型为良式：

1-2) 行为未定义，除非 static_cast<T*>((U*)nullptr) 为良式。
3-4) 行为未定义，除非 dynamic_cast<T*>((U*)nullptr) 为良式。
5-6) 行为未定义，除非 const_cast<T*>((U*)nullptr) 为良式。
7-8) 行为未定义，除非 reinterpret_cast<T*>((U*)nullptr) 为良式。

调用右值重载 (2,4,6,8) 后， `r` 为空且 r.get() == nullptr ，除了对于 `dynamic_pointer_cast` (4) ，若 dynamic_cast 失败则不修改 `r` 。 | (C++20 起)

### 参数

r | - | 要转换的指针

### 注意

表达式 std::shared_ptr<T>(static_cast<T*>(r.get())) 、 std::shared_ptr<T>(dynamic_cast<T*>(r.get())) 及 std::shared_ptr<T>(const_cast<T*>(r.get())) 看起来可能拥有相同效果，但它们全都很可能导致未定义行为，试图删除同一对象二次！

### 可能的实现

版本一
    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);
    }
版本二
    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>();
        }
    }
版本三
    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);
    }

### 示例

    #include <iostream>
    #include <memory>

    struct BaseClass {};

    struct DerivedClass : BaseClass
    {
        void f() const
        {
            std::cout << "Hello World!\n";
        }
        ~DerivedClass(){ // 注意：它不是虚的
            std::cout << "~DerivedClass\n";
        }
    };

    int main()
    {
        std::shared_ptr<BaseClass> ptr_to_base(std::make_shared<DerivedClass>());

        // ptr_to_base->f(); // 错误不会编译： BaseClass 无名为 'f' 的成员

        std::static_pointer_cast<DerivedClass>(ptr_to_base)->f(); // OK
        // （构造临时 shared_ptr ，然后调用 operator-> ）

        static_cast<DerivedClass*>(ptr_to_base.get())->f(); // 亦 OK
        // （直接转型，不构造临时 shared_ptr ）
    }

输出：

    Hello World!
    Hello World!
    ~DerivedClass

### 参阅

(构造函数) | 构造新的 `shared_ptr` (公开成员函数)