有什么用途:
static_cast
dynamic_cast
const_cast
reinterpret_cast
- C风格演员
(type)value
- 功能式演员
type(value)
如何确定在哪些特定情况下使用哪个?
有什么用途:
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
将失败。即使这样,也要考虑更长,更明确的选择。
执行a时,C风格的强制转换也会忽略访问控制 static_cast
,这意味着他们有能力执行其他演员无法进行的操作。不过,这主要是一个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);
}
如果你对内部有点了解,它可能会有所帮助......
的static_cast
A*
至 B*
如果A和B在继承层次结构(或void)中,则总是成功,否则会出现编译错误。A&
至 B&
。的dynamic_cast
(Base*)
至 (Derived*)
如果指针实际上不是派生类型,则可能会失败。A*
至 B*
,如果强制转换无效,那么dynamic_cast将返回nullptr。A&
至 B&
如果强制转换无效,则dynamic_cast将抛出bad_cast异常。const_cast会
set<T>
它仅将其元素作为const返回,以确保您不更改其键。但是,如果您的目的是修改对象的非关键成员,那么它应该没问题。您可以使用const_cast删除constness。T& foo()
以及 const T& foo()
。为避免代码重复,可以应用const_cast从一个函数返回另一个函数的值。reinterpret_cast的
是否 这个 回答你的问题?
我从来没用过 reinterpret_cast
并且想知道是否遇到需要它的情况并不是一种糟糕的设计气味。在我的代码库中工作 dynamic_cast
经常使用。与...的区别 static_cast
是那个 dynamic_cast
做运行时检查可能(更安全)或不可能(更多开销)是你想要的(见 MSDN)。
除了到目前为止的其他答案,这里是不明显的例子 static_cast
是不够的 reinterpret_cast
需要。假设有一个函数在输出参数中返回指向不同类的对象(不共享公共基类)的指针。这种功能的一个真实例子是 CoCreateInstance()
(参见最后一个参数,实际上是这个参数 void**
)。假设您从此函数请求特定的对象类,因此您事先知道指针的类型(您经常为COM对象执行此操作)。在这种情况下,您无法将指针指向您的指针 void**
同 static_cast
: 你需要 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);