有什么用途:
static_cast
dynamic_cast
const_cast
reinterpret_cast
(type)value
type(value)
如何确定在哪些特定情况下使用哪个?
static_cast
是您应该尝试使用的第一个演员。它执行类似类型之间的隐式转换(例如int
到float
或指向void*
指针),它还可以调用显式转换函数(或隐式转换函数)。在许多情况下,明确声明static_cast
不是必需的,但重要的是要注意T(something)
语法等同于(T)something
并且应该避免(稍后会详细说明)。但是, T(something, something_else)
是安全的,并且保证可以调用构造函数。
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)
强制转换。 C 样式转换定义为以下第一个成功:
const_cast
static_cast
(虽然忽略了访问限制) static_cast
(见上文),然后是const_cast
reinterpret_cast
reinterpret_cast
,然后是const_cast
因此,它可以在某些情况下用作其他强制转换的替代品,但由于能够转换为reinterpret_cast
,因此非常危险,后者应该在需要显式强制转换时首选,除非您确定static_cast
将成功或reinterpret_cast
将失败。即使这样,也要考虑更长,更明确的选择。
执行static_cast
,C 风格的强制转换也会忽略访问控制,这意味着它们可以执行其他强制转换无法执行的操作。不过,这主要是一个 kludge,在我看来,这是避免 C 风格演员阵容的另一个原因。
使用dynamic_cast
转换继承层次结构中的指针 / 引用。
使用static_cast
进行普通类型转换。
使用reinterpret_cast
进行低级重新解释位模式。使用时要格外小心。
使用const_cast
来抛弃const/volatile
。除非你使用 const 不正确的 API,否则请避免这种情况。
(上面已经给出了很多理论和概念上的解释)
下面是我使用static_cast , dynamic_cast , const_cast , reinterpret_cast时的一些实际例子 。
(另请参阅此内容以理解解释: http : //www.cplusplus.com/doc/tutorial/typecasting/ )
static_cast:
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:
typedef unsigned short uint16;
// Read Bytes returns that 2 bytes got read.
bool ByteBuffer::ReadUInt16(uint16& val) {
return ReadBytes(reinterpret_cast<char*>(&val), 2);
}