zoukankan      html  css  js  c++  java
  • c++智能指针转化:static_pointer_cast、dynamic_pointer_cast、const_pointer_cast、reinterpret_pointer_cast

    转自:https://blog.csdn.net/sunlin972913894/article/details/108427587

    C++基类和派生类的智能指针转换:static_pointer_cast、dynamic_pointer_cast、const_pointer_cast、reinterpret_pointer_cast
    当我们用“裸”指针进行类层次上的上下行转换时,可以使用dynamic_cast。当然我们也可以使用static_cast,只是dynamic_cast在进行下行转换的时候(即基类到派生类)具有类型检查功能,而static_cast没有。因此存在安全问题。

    当我们使用智能指针时,如果需要进行类层次上的上下行转换时,可以使用std::static_pointer_cast()、std::dynamic_pointer_cast、std::const_pointer_cast()和std::reinterpret_pointer_cast()。它们的功能和std::static_cast()、std::dynamic_cast、std::const_cast()和std::reinterpret_cast()类似,只不过转换的是智能指针std::shared_ptr,返回的也是std::shared_ptr类型。

    1、std::static_pointer_cast():当指针是智能指针时候,向上转换,用static_cast 则转换不了,此时需要使用static_pointer_cast。

    2、std::dynamic_pointer_cast():当指针是智能指针时候,向下转换,用dynamic_cast 则转换不了,此时需要使用dynamic_pointer_cast(此处注意:base基类需要至少有一个virtual成员函数(即多态类型)才能允许动态强制转换,否则编译报错)。

    3、std::const_pointer_cast():功能与std::const_cast()类似

    4、std::reinterpret_pointer_cast():功能与std::reinterpret_cast()类似

    Defined in header <memory>


    template< class T, class U >
    std::shared_ptr<T> static_pointer_cast( const std::shared_ptr<U>& r ) noexcept;

    (1) (since C++11)
    template< class T, class U >
    std::shared_ptr<T> static_pointer_cast( std::shared_ptr<U>&& r ) noexcept;

    (2) (since C++20)
    template< class T, class U >
    std::shared_ptr<T> dynamic_pointer_cast( const std::shared_ptr<U>& r ) noexcept;

    (3) (since C++11)
    template< class T, class U >
    std::shared_ptr<T> dynamic_pointer_cast( std::shared_ptr<U>&& r ) noexcept;

    (4) (since C++20)
    template< class T, class U >
    std::shared_ptr<T> const_pointer_cast( const std::shared_ptr<U>& r ) noexcept;

    (5) (since C++11)
    template< class T, class U >
    std::shared_ptr<T> const_pointer_cast( std::shared_ptr<U>&& r ) noexcept;

    (6) (since C++20)
    template< class T, class U >
    std::shared_ptr<T> reinterpret_pointer_cast( const std::shared_ptr<U>& r ) noexcept;

    (7) (since C++17)
    template< class T, class U >
    std::shared_ptr<T> reinterpret_pointer_cast( std::shared_ptr<U>&& r ) noexcept;

    (8) (since C++20)
    基类和派生类的智能指针转换要使用std::dynamic_pointer_cast和std::static_pointer_cast。由于std::dynamic_pointer_cast和dynamic_cast原理一样,std::static_pointer_cast和static_cast原理一样

    Creates a new instance of std::shared_ptr whose stored pointer is obtained from r's stored pointer using a cast expression.

    If r is empty, so is the new shared_ptr (but its stored pointer is not necessarily null). Otherwise, the new shared_ptr will share ownership with the initial value of r, except that it is empty if the dynamic_cast performed by dynamic_pointer_cast returns a null pointer.

    Let Y be typename std::shared_ptr<T>::element_type, then the resulting std::shared_ptr's stored pointer will be obtained by evaluating, respectively:

    1-2) static_cast<Y*>(r.get()).

    3-4) dynamic_cast<Y*>(r.get()) (If the result of the dynamic_cast is a null pointer value, the returned shared_ptr will be empty.)

    5-6) const_cast<Y*>(r.get()).

    7-8) reinterpret_cast<Y*>(r.get())

    The behavior of these functions is undefined unless the corresponding cast from U* to T* is well formed:

    1-2) The behavior is undefined unless static_cast<T*>((U*)nullptr) is well formed.

    3-4) The behavior is undefined unless dynamic_cast<T*>((U*)nullptr) is well formed.

    5-6) The behavior is undefined unless const_cast<T*>((U*)nullptr) is well formed.

    7-8) The behavior is undefined unless reinterpret_cast<T*>((U*)nullptr) is well formed.

    After calling the rvalue overloads (2,4,6,8), r is empty and r.get() == nullptr, except that r is not modified for dynamic_pointer_cast (4) if the dynamic_cast fails.

    (since C++20)
    Parameters
    r - The pointer to convert
    Notes
    The expressions std::shared_ptr<T>(static_cast<T*>(r.get())), std::shared_ptr<T>(dynamic_cast<T*>(r.get())) and std::shared_ptr<T>(const_cast<T*>(r.get())) might seem to have the same effect, but they all will likely result in undefined behavior, attempting to delete the same object twice!

    Possible implementation
    1、std::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);
    }
    2、std::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>();
    }
    }
    3、std::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);
    }
    4、std::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);
    }
    使用示例:

    #include <iostream>
    #include <memory>

    struct Base
    {
    int a;
    virtual void f() const { std::cout << "I am base!\n";}
    virtual ~Base(){}
    };

    struct Derived : Base
    {
    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";
    }
    Output:

    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
    示例2
    #include <iostream> // std::cout std::endl
    #include <memory> // std::shared_ptr std::dynamic_pointer_cast std::static_pointer_cast

    class base
    {
    public:
    virtual ~base(void) = default;
    };

    class derived : public base
    {
    };

    class test : public base
    {
    };

    int main(void)
    {
    std::cout << std::boolalpha;

    // 两个不同的派生类对象
    auto derivedobj = std::make_shared<derived>();
    auto testobj = std::make_shared<test>();

    // 隐式转换 derived->base
    std::shared_ptr<base> pointer1 = derivedobj;

    // static_pointer_cast derived->base
    auto pointer2 = std::static_pointer_cast<base>(derivedobj);

    // dynamic_pointer_cast base->derived
    auto pointer3 = std::dynamic_pointer_cast<derived>(pointer1);
    std::cout << (pointer3 == nullptr) << std::endl;

    // dynamic_pointer_cast base->derived
    auto pointer4 = std::dynamic_pointer_cast<test>(pointer1);
    std::cout << (pointer4 == nullptr) << std::endl;

    return 0;
    }
    输出结果:

    false
    true
    std::reinterpret_pointer_cast()和std::const_pointer_cast()示例:

    #include <memory>
    #include <cassert>
    #include <cstdint>

    int main()
    {
    std::shared_ptr<int> foo;
    std::shared_ptr<const int> bar;

    foo = std::make_shared<int>(10);

    bar = std::const_pointer_cast<const int>(foo);

    std::cout << "*bar: " << *bar << std::endl;
    *foo = 20;
    std::cout << "*bar: " << *bar << std::endl;

    std::shared_ptr<std::int8_t[]> p(new std::int8_t[4]{1, 1, 1, 1});
    std::shared_ptr<std::int32_t[]> q = std::reinterpret_pointer_cast<std::int32_t[]>(p);

    std::int32_t r = q[0];

    std::int32_t x = (1 << 8) | (1 << 16) | (1 << 24) | 1;
    assert(r == x);

    return 0;
    }
    输出:

    *bar: 10
    *bar: 20
    Press <RETURN> to close this window...

  • 相关阅读:
    Java反射机制(创建Class对象的三种方式)
    webservice原理及基于cxf开发的基本流程
    开始打开eclipse .exe时候显示找不到jre路径
    Token验证详解
    RPC远程协议之Thrift入门
    RPC远程协议之原理分析
    Jmeter进行性能测试时多台负载机的配置方法
    Jmeter分布式部署测试-----远程连接多台电脑做压力性能测试
    Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例
    理解Cookie和Session机制
  • 原文地址:https://www.cnblogs.com/liangzige/p/15589054.html
Copyright © 2011-2022 走看看