何时应该使用static_cast,dynamic_cast,const_cast和reinterpret_cast?

的正确用法是: windows

  • static_cast
  • dynamic_cast
  • const_cast
  • reinterpret_cast
  • C样式转换(type)value
  • 函数样式转换type(value)

如何决定在特定状况下使用哪一个? 安全


#1楼

(上面已经给出了不少理论和概念上的解释) 函数

下面是当我使用static_castdynamic_castconst_castreinterpret_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);
}

#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);

#3楼

这能回答您的问题吗?

我历来没有使用过reinterpret_cast ,而且想知道是否遇到须要它的状况不会引发不良设计的味道。 在我处理dynamic_cast的代码库中,使用了不少代码。 与static_cast的区别在于, dynamic_cast会进行运行时检查,这可能(更安全)或可能(更多开销)不是您想要的(请参阅msdn )。


#4楼

使用dynamic_cast在继承层次结构中转换指针/引用。

使用static_cast进行普通类型转换。

使用reinterpret_cast对位模式进行低级从新解释。 使用时要格外当心。

使用const_cast放弃const/volatile 。 除非您使用const不正确的API,不然请避免这种状况。


#5楼

static_cast是您应该尝试使用的第一个演员表。 它的做用相似于类型之间的隐式转换(例如intfloat或指向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_castvolatile上也相似地工做,尽管这种状况不太常见。


dynamic_cast仅用于处理多态。 您能够将任何多态类型的指针或引用强制转换为任何其余类类型(多态类型至少具备一个声明或继承的虚函数)。 您不只能够向下投射,还可使用它–您能够侧向投射,甚至向上投射另外一个链。 dynamic_cast将查找所需的对象,并在可能的状况下将其返回。 若是不能,则在使用指针的状况下将返回nullptr ,在使用引用的状况下将返回std::bad_cast

dynamic_cast有一些限制。 若是继承层次结构中有多个相同类型的对象(所谓的“可怕的钻石”),而且您没有使用virtual继承,则该方法将无效。 它也只能进行公共继承-它将始终没法经过protected继承或private继承。 可是,这不多有问题,由于这种继承形式不多。


reinterpret_cast是最危险的强制类型转换,应谨慎使用。 它将一种类型直接转换为另外一种类型-例如将值从一个指针转换为另外一种指针,或将指针存储在int或其余各类讨厌的东西中。 在很大程度上,只有保证你获得reinterpret_cast是,一般,若是你把结果返回到原来的类型,你会获得的值彻底相同( 若是中间型比原来的类型更小)。 reinterpret_cast也没法完成许多转换。 它主要用于特别奇怪的转换和位操做,例如将原始数据流转换为实际数据,或将数据存储在指向对齐数据的指针的低位。


C样式转换和函数样式转换分别是使用(type)objecttype(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样式强制转换的另外一个缘由。

相关文章
相关标签/搜索