news 2026/4/17 19:36:14

c++智能指针转化:static_pointer_cast、dynamic_pointer_cast、const_pointer_cast、reinterpret_pointer_cast 相关函数梳

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 4:29:20

7、无线网络与复杂网络配置指南

无线网络与复杂网络配置指南 1. 无线网络用户规则配置 在无线网络环境中,不同用户的需求和权限可能存在差异。以Windows用户Peter和OpenBSD用户Christina为例,我们可以为他们分别设置不同的规则。 Peter仅需上网浏览和访问特定机器上的高端口服务,可在 /etc/authpf/user…

作者头像 李华
网站建设 2026/4/10 20:10:07

Perl Socket 编程

Perl Socket 编程 引言 Perl(Practical Extraction and Report Language)是一种强大的编程语言,广泛应用于文本处理、系统管理、网络编程等领域。在众多应用中,Perl Socket 编程以其简洁、高效的特点备受青睐。本文将详细介绍Perl Socket编程的基础知识、常用方法以及在实…

作者头像 李华
网站建设 2026/4/14 0:40:52

SSC Tools配置项中文详解

一、基础工程与版本配置 在 SSC Tool 主页面&#xff08;SSC-Device界面&#xff09;&#xff0c;首先显示工程的基础配置信息&#xff0c;决定协议栈版本与核心文件关联&#xff0c;是后续配置的前提&#xff1a; 配置项说明与作用关键约束与示例SSC Version显示当前 SSC Too…

作者头像 李华
网站建设 2026/4/14 15:05:15

深入理解 FactoryBean:定制化 Bean 的秘密武器

前言在 Spring 的日常开发中&#xff0c;我们通常使用 Component、Service 或者 Configuration Bean 的方式来定义 Bean。对于大多数简单的对象&#xff08;比如 Controller、Service&#xff09;&#xff0c;这些方式非常直观且高效。但是&#xff0c;假设我们需要创建一个初…

作者头像 李华
网站建设 2026/4/8 20:23:35

金融合规监控规则设计实战(20年专家经验倾囊相授)

第一章&#xff1a;金融合规 Agent 的监控规则概述在现代金融科技架构中&#xff0c;金融合规 Agent 作为实时监控与风险识别的核心组件&#xff0c;承担着确保交易行为符合监管要求的关键职责。该 Agent 通过预设的监控规则集&#xff0c;对资金流动、用户操作及交易模式进行自…

作者头像 李华