的正确用法是: windows
static_cast
dynamic_cast
const_cast
reinterpret_cast
(type)value
type(value)
如何决定在特定状况下使用哪一个? 安全
(上面已经给出了不少理论和概念上的解释) 函数
下面是当我使用static_cast , dynamic_cast , const_cast , reinterpret_cast时的一些实际示例 。 ui
(也参考此以理解说明: http : //www.cplusplus.com/doc/tutorial/typecasting/ ) spa
static_cast: debug
OnEventData(void* pData) { ...... // pData is a void* pData, // EventData is a structure e.g. // typedef struct _EventData { // std::string id; // std:: string remote_id; // } EventData; // On Some Situation a void pointer *pData // has been static_casted as // EventData* pointer EventData *evtdata = static_cast<EventData*>(pData); ..... }
dynamic_cast: 设计
void DebugLog::OnMessage(Message *msg) { static DebugMsgData *debug; static XYZMsgData *xyz; if(debug = dynamic_cast<DebugMsgData*>(msg->pdata)){ // debug message } else if(xyz = dynamic_cast<XYZMsgData*>(msg->pdata)){ // xyz message } else/* if( ... )*/{ // ... } }
const_cast: 指针
// *Passwd declared as a const const unsigned char *Passwd // on some situation it require to remove its constness const_cast<unsigned char*>(Passwd)
reinterpret_cast: code
typedef unsigned short uint16; // Read Bytes returns that 2 bytes got read. bool ByteBuffer::ReadUInt16(uint16& val) { return ReadBytes(reinterpret_cast<char*>(&val), 2); }
除了到目前为止的其余答案以外,这是一个显而易见的示例,其中static_cast
不足,所以须要reinterpret_cast
。 假设有一个函数,该函数在输出参数中返回指向不一样类(不共享公共基类)的对象的指针。 此类函数的真实示例是CoCreateInstance()
(请参阅最后一个参数,其实是void**
)。 假设您今后函数请求特定的对象类,所以您预先知道了指针的类型(一般对COM对象执行此操做)。 在这种状况下,您没法使用static_cast
将指针转换为void**
:您须要reinterpret_cast<void**>(&yourPointer)
。 对象
在代码中:
#include <windows.h> #include <netfw.h> ..... INetFwPolicy2* pNetFwPolicy2 = nullptr; HRESULT hr = CoCreateInstance(__uuidof(NetFwPolicy2), nullptr, CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2), //static_cast<void**>(&pNetFwPolicy2) would give a compile error reinterpret_cast<void**>(&pNetFwPolicy2) );
可是, static_cast
适用于简单的指针(而不是指向指针的指针),所以能够经过如下方式重写以上代码,以免reinterpret_cast
(以额外的变量为代价):
#include <windows.h> #include <netfw.h> ..... INetFwPolicy2* pNetFwPolicy2 = nullptr; void* tmp = nullptr; HRESULT hr = CoCreateInstance(__uuidof(NetFwPolicy2), nullptr, CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2), &tmp ); pNetFwPolicy2 = static_cast<INetFwPolicy2*>(tmp);
这能回答您的问题吗?
我历来没有使用过reinterpret_cast
,而且想知道是否遇到须要它的状况不会引发不良设计的味道。 在我处理dynamic_cast
的代码库中,使用了不少代码。 与static_cast
的区别在于, dynamic_cast
会进行运行时检查,这可能(更安全)或可能(更多开销)不是您想要的(请参阅msdn )。
使用dynamic_cast
在继承层次结构中转换指针/引用。
使用static_cast
进行普通类型转换。
使用reinterpret_cast
对位模式进行低级从新解释。 使用时要格外当心。
使用const_cast
放弃const/volatile
。 除非您使用const不正确的API,不然请避免这种状况。
static_cast
是您应该尝试使用的第一个演员表。 它的做用相似于类型之间的隐式转换(例如int
到float
或指向void*
指针),它还能够调用显式转换函数(或隐式函数)。 在许多状况下,无需明确声明static_cast
,但必须注意, T(something)
语法与(T)something
等效,应避免使用(稍后会详细介绍)。 T(something, something_else)
是安全的,而且保证能够调用构造函数。
static_cast
也能够经过继承层次结构进行static_cast
。 向上(朝向基类)进行强制转换时没有必要,可是向下转换时只要不经过virtual
继承进行转换就可使用。 可是,它不进行检查,而且将层次结构static_cast
下降为实际上不是对象类型的类型是未定义的行为。
const_cast
可用于将const
删除或添加到变量; 没有其余C ++强制转换可以将其删除(甚至不能reinterpret_cast
)。 重要的是要注意,仅当原始变量为const
,才能够修改之前的const
值; 若是使用它来使const
脱离对未使用const
声明的内容的引用,则这是安全的。 例如,这在基于const
重载成员函数时颇有用。 它还能够用于向对象添加const
,例如调用成员函数重载。
const_cast
在volatile
上也相似地工做,尽管这种状况不太常见。
dynamic_cast
仅用于处理多态。 您能够将任何多态类型的指针或引用强制转换为任何其余类类型(多态类型至少具备一个声明或继承的虚函数)。 您不只能够向下投射,还可使用它–您能够侧向投射,甚至向上投射另外一个链。 dynamic_cast
将查找所需的对象,并在可能的状况下将其返回。 若是不能,则在使用指针的状况下将返回nullptr
,在使用引用的状况下将返回std::bad_cast
。
dynamic_cast
有一些限制。 若是继承层次结构中有多个相同类型的对象(所谓的“可怕的钻石”),而且您没有使用virtual
继承,则该方法将无效。 它也只能进行公共继承-它将始终没法经过protected
继承或private
继承。 可是,这不多有问题,由于这种继承形式不多。
reinterpret_cast
是最危险的强制类型转换,应谨慎使用。 它将一种类型直接转换为另外一种类型-例如将值从一个指针转换为另外一种指针,或将指针存储在int
或其余各类讨厌的东西中。 在很大程度上,只有保证你获得reinterpret_cast
是,一般,若是你把结果返回到原来的类型,你会获得的值彻底相同( 但若是中间型比原来的类型更小)。 reinterpret_cast
也没法完成许多转换。 它主要用于特别奇怪的转换和位操做,例如将原始数据流转换为实际数据,或将数据存储在指向对齐数据的指针的低位。
C样式转换和函数样式转换分别是使用(type)object
或type(object)
进行的转换,而且在功能上等效。 它们被定义为如下成功的第一个:
const_cast
static_cast
(尽管忽略访问限制) static_cast
(请参见上文),而后是const_cast
reinterpret_cast
reinterpret_cast
,而后是const_cast
所以,在某些状况下,它能够替代其余类型的转换,可是因为有能力降级到reinterpret_cast
,所以很是危险,而且在须要显式转换时应首选后者,除非您肯定static_cast
将成功或reinterpret_cast
将失败。 即便这样,也能够考虑使用更长,更明确的选项。
C样式强制转换在执行static_cast
时也会忽略访问控制,这意味着它们具备执行其余强制转换没法执行的操做的能力。 可是,这主要是一种争执,在我看来,这是避免使用C样式强制转换的另外一个缘由。