What are the proper uses of:
正确的用途是什么:
static_cast
- static_cast
dynamic_cast
- dynamic_cast
const_cast
- const_cast
reinterpret_cast
- reinterpret_cast
- C-style cast
(type)value
- c风格的演员(类型)的价值
- Function-style cast
type(value)
- Function-style演员类型(值)
How does one decide which to use in which specific cases?
如何决定在哪些特定情况下使用哪一种?
6 个解决方案
#1
2187
static_cast
is the first cast you should attempt to use. It does things like implicit conversions between types (such as int
to float
, or pointer to void*
), and it can also call explicit conversion functions (or implicit ones). In many cases, explicitly stating static_cast
isn't necessary, but it's important to note that the T(something)
syntax is equivalent to (T)something
and should be avoided (more on that later). A T(something, something_else)
is safe, however, and guaranteed to call the constructor.
static_cast是您应该尝试使用的第一个强制类型转换。它在类型之间进行隐式转换(比如int to float,或者指针to void*),还可以调用显式转换函数(或隐式转换函数)。在许多情况下,显式地声明static_cast不是必需的,但是需要注意的是,T(某物)语法等同于(T)某物,应该避免(稍后详细讨论)。然而,T(something, something_else)是安全的,并且保证调用构造函数。
static_cast
can also cast through inheritance hierarchies. It is unnecessary when casting upwards (towards a base class), but when casting downwards it can be used as long as it doesn't cast through virtual
inheritance. It does not do checking, however, and it is undefined behavior to static_cast
down a hierarchy to a type that isn't actually the type of the object.
static_cast也可以通过继承层次结构进行强制转换。向上抛出(指向基类)是不必要的,但向下抛出时,只要不通过虚继承就可以使用。但是,它不进行检查,并且static_cast一个层次结构到一个实际上不是对象类型的类型是未定义的行为。
const_cast
can be used to remove or add const
to a variable; no other C++ cast is capable of removing it (not even reinterpret_cast
). It is important to note that modifying a formerly const
value is only undefined if the original variable is const
; if you use it to take the const
off a reference to something that wasn't declared with const
, it is safe. This can be useful when overloading member functions based on const
, for instance. It can also be used to add const
to an object, such as to call a member function overload.
const_cast可用于删除或向变量添加const;没有其他c++强制转换能够删除它(甚至不能重新解释强制转换)。需要注意的是,只有当原始变量为const时,修改以前的const值才是未定义的;如果你用它来指代那些与const没有声明的东西,它是安全的。例如,当基于const的重载成员函数时,这一点很有用。它还可以用于向对象添加const,例如调用成员函数重载。
const_cast
also works similarly on volatile
, though that's less common.
const_cast在volatile上也有类似的工作,不过这种情况并不常见。
dynamic_cast
is almost exclusively used for handling polymorphism. You can cast a pointer or reference to any polymorphic type to any other class type (a polymorphic type has at least one virtual function, declared or inherited). You can use it for more than just casting downwards -- you can cast sideways or even up another chain. The dynamic_cast
will seek out the desired object and return it if possible. If it can't, it will return nullptr
in the case of a pointer, or throw std::bad_cast
in the case of a reference.
dynamic_cast几乎只用于处理多态性。您可以将任何多态类型的指针或引用投射到任何其他类类型(多态类型至少有一个虚拟函数,声明或继承)。你可以使用它不仅仅是向下投射——你可以向一边投射,甚至向上投射另一条链条。dynamic_cast将查找所需的对象并在可能的情况下返回它。如果不能,它将在指针的情况下返回nullptr,或者在引用时抛出std::bad_cast。
dynamic_cast
has some limitations, though. It doesn't work if there are multiple objects of the same type in the inheritance hierarchy (the so-called 'dreaded diamond') and you aren't using virtual
inheritance. It also can only go through public inheritance - it will always fail to travel through protected
or private
inheritance. This is rarely an issue, however, as such forms of inheritance are rare.
然而,dynamic_cast有一些局限性。如果继承层次结构中有相同类型的多个对象(所谓的“可怕的钻石”),并且您没有使用虚拟继承,那么它就不起作用了。它也只能通过公共继承——它将永远不能通过受保护的或私有继承。然而,这很少是一个问题,因为这种继承形式很少见。
reinterpret_cast
is the most dangerous cast, and should be used very sparingly. It turns one type directly into another - such as casting the value from one pointer to another, or storing a pointer in an int
, or all sorts of other nasty things. Largely, the only guarantee you get with reinterpret_cast
is that normally if you cast the result back to the original type, you will get the exact same value (but not if the intermediate type is smaller than the original type). There are a number of conversions that reinterpret_cast
cannot do, too. It's used primarily for particularly weird conversions and bit manipulations, like turning a raw data stream into actual data, or storing data in the low bits of an aligned pointer.
reinterpret_cast是最危险的cast,应该非常谨慎地使用它。它将一种类型直接转换为另一种类型,比如将值从一个指针转换到另一个指针,或者将指针存储在int中,或者其他各种令人讨厌的东西。在很大程度上,只有当您将结果返回到原始类型时,您才能得到的唯一保证是,您将得到完全相同的值(但如果中间类型小于原始类型的话)。有许多转换是reinterpret_cast不能做的。它主要用于特别奇怪的转换和位操作,如将原始数据流转换为实际数据,或将数据存储在对齐指针的低位。
C-style cast and function-style cast are casts using (type)object
or type(object)
, respectively. A C-style cast is defined as the first of the following which succeeds:
c样式强制转换和函数样式强制转换分别使用(类型)对象或类型(对象)。c型铸造被定义为以下第一个成功的铸造:
const_cast
- const_cast
-
static_cast
(though ignoring access restrictions) - static_cast(尽管忽略访问限制)
-
static_cast
(see above), thenconst_cast
- static_cast(见上面),然后是const_cast。
reinterpret_cast
- reinterpret_cast
-
reinterpret_cast
, thenconst_cast
- reinterpret_cast,然后const_cast
It can therefore be used as a replacement for other casts in some instances, but can be extremely dangerous because of the ability to devolve into a reinterpret_cast
, and the latter should be preferred when explicit casting is needed, unless you are sure static_cast
will succeed or reinterpret_cast
will fail. Even then, consider the longer, more explicit option.
因此,在某些情况下,它可以作为其他类型转换的替代,但是由于可以将其转换为reviewt_cast,因此可能非常危险,而在需要显式转换时,应该首选后者,除非您确信static_cast将成功或重新解释t_cast将失败。即便如此,也要考虑更长的、更明确的选择。
C-style casts also ignore access control when performing a static_cast
, which means that they have the ability to perform an operation that no other cast can. This is mostly a kludge, though, and in my mind is just another reason to avoid C-style casts.
c样式的强制转换在执行static_cast时也忽略了访问控制,这意味着它们可以执行其他强制转换无法执行的操作。不过,在我看来,这主要是一种拼凑的东西,这只是避免使用c风格的数据类型转换的另一个原因。
#2
276
Use dynamic_cast
for converting pointers/references within an inheritance hierarchy.
使用dynamic_cast在继承层次结构中转换指针/引用。
Use static_cast
for ordinary type conversions.
对于普通类型转换,使用static_cast。
Use reinterpret_cast
for low-level reinterpreting of bit patterns. Use with extreme caution.
使用reinterpretation t_cast对位模式进行低级的重新解释。使用极端谨慎。
Use const_cast
for casting away const/volatile
. Avoid this unless you are stuck using a const-incorrect API.
使用const_cast来丢弃const/volatile。避免这种情况,除非您使用了不正确的API。
#3
147
(A lot of theoretical and conceptual explanation has been given above)
(以上给出了很多理论和概念上的解释)
Below are some of the practical examples when I used static_cast, dynamic_cast, const_cast, reinterpret_cast.
下面是一些实际的例子,我使用static_cast、dynamic_cast、const_cast、reviewt_cast。
(Also referes this to understand the explaination : http://www.cplusplus.com/doc/tutorial/typecasting/)
(这也可以用来理解解释:http://www.cplusplus.com/doc/tutorial/typecasting/)
static_cast :
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 :
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 :
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 :
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);
}
#4
48
It might help if you know little bit of internals...
如果你了解一些内部因素,可能会有所帮助。
static_cast
static_cast
- C++ compiler already knows how to convert scaler types such as float to int. Use static_cast for them.
- c++编译器已经知道如何转换标量类型,例如float到int。使用static_cast。
- In general, while converting type A to B, static_cast would call B's constructor passing it A. If B doesn't have such constructor then you get compile time error.
- 一般来说,当将类型A转换为B时,static_cast会调用B的构造函数传递A。如果B没有这样的构造函数,那么就会出现编译时间错误。
- Cast from
A*
toB*
always succeeds if A and B are in inheritance hierarchy (or void) otherwise you get compile error. - 如果A和B处于继承层次结构(或void)中,则从A*强制转换为B*总是成功的,否则会导致编译错误。
- Gotcha: If you cast base pointer to derived pointer but if actual object is if not derived type then you don't get error. You get bad pointer and as soon as you try to access members of derived pointer, you get segfault at runtime.
- 如果你将基指针转换成派生指针,但如果实际对象不是派生类型,那么你不会得到错误。当你试图访问派生指针的成员时,你会得到一个坏指针,你会在运行时得到segfault。
- Same goes for
A&
toB&
. - a&b也是一样。
- Gotcha: Cast from Derived to Base or viceversa creates new copy! For people coming from C#/Java, many of above can be a huge surprise.
- 捕获:从派生到基或viceversa创建新副本!对于来自c# /Java的人来说,上面的许多内容可能是一个巨大的惊喜。
dynamic_cast
dynamic_cast
- dynamic_cast uses runtime type information to figure out if cast is valid. For example,
(Base*)
to(Derived*)
may fail if pointer is not actually of derived type. - dynamic_cast使用运行时类型信息来确定cast是否有效。例如,如果指针实际上不是派生类型,则(Base*)到(派生*)可能会失败。
- This means, dynamic_cast is very expensive compared to static_cast!
- 这意味着,与static_cast相比,dynamic_cast非常昂贵!
- For
A*
toB*
, if cast is invalid then dynamic_cast will return nullptr. - 对于A*到B*,如果强制转换无效,那么dynamic_cast将返回nullptr。
- For
A&
toB&
if cast is invalid then dynamic_cast will throw bad_cast exception. - 对于a&to b&if强制转换无效,那么dynamic_cast将抛出bad_cast异常。
const_cast
const_cast
- While static_cast can do non-const to const it can't go other way around. The const_cast can do both ways.
- 虽然static_cast可以执行非const命令,但它不能执行其他方式。const_cast可以有两种方式。
- One example where this comes handy is iterating through some container like
set<T>
which only returns its elements as const to make sure you don't change its key. However if your intent is to modify object's non-key members then it should be ok. You can use const_cast to remove constness. -
这很方便的一个例子是迭代某个容器,比如set
,它只返回其元素const,以确保不更改其键。但是,如果您的意图是修改对象的非关键成员,那么它应该是可以的。您可以使用const_cast来消除一致性。 - Another example is when you want to implement
T& foo()
as well asconst T& foo()
. To avoid code duplication, you can apply const_cast to return value of one function from another. - 另一个例子是当您希望实现t&foo()以及const t&foo()时。为了避免代码重复,可以应用const_cast从另一个函数返回值。
- Unlike above two casts, there is runtime overhead.
- 与上面两个类型不同,这里有运行时开销。
reinterpret_cast
reinterpret_cast
- This basically says that take these bytes at this memory location and think of it as given object.
- 这基本上是说,在这个内存位置取这些字节并把它想象成给定的对象。
- For example, you can load 4 bytes of float to 4 bytes of int to see how bits in float looks like.
- 例如,您可以加载4字节的浮点数到4字节的int数,以了解浮点数中的位数是什么样子的。
- Obviously, if data is not correct for the type, you may get segfault.
- 显然,如果数据对类型不正确,您可能会得到segfault。
- There is no runtime overhead for this cast.
- 这个转换没有运行时开销。
#5
11
Does this answer your question?
这能回答你的问题吗?
I have never used reinterpret_cast
, and wonder whether running into a case that needs it isn't a smell of bad design. In the code base I work on dynamic_cast
is used a lot. The difference with static_cast
is that a dynamic_cast
does runtime checking which may (safer) or may not (more overhead) be what you want (see msdn).
我从来没有使用过reinterpret_cast,我想知道遇到一个需要它的案例是否有不好的设计味道。在我的代码库中,经常使用dynamic_cast。与static_cast不同的是,dynamic_cast执行的运行时检查可能(更安全),也可能(更多开销)是您想要的(请参阅msdn)。
#6
9
In addition to the other answers so far, here is unobvious example where static_cast
is not sufficient so that reinterpret_cast
is needed. Suppose there is a function which in an output parameter returns pointers to objects of different classes (which do not share a common base class). A real example of such function is CoCreateInstance()
(see the last parameter, which is in fact void**
). Suppose you request particular class of object from this function, so you know in advance the type for the pointer (which you often do for COM objects). In this case you cannot cast pointer to your pointer into void**
with static_cast
: you need reinterpret_cast<void**>(&yourPointer)
.
除了到目前为止的其他答案之外,这里还有一个不明显的示例,说明static_cast不够,因此需要reinterpret_cast。假设有一个函数,它在输出参数中返回指向不同类的对象的指针(它们不共享公共基类)。此类函数的一个真实示例是CoCreateInstance()(请参阅最后一个参数,它实际上是void**)。假设您从这个函数中请求特定的对象类,以便预先知道指针的类型(通常对COM对象这样做)。在这种情况下,您不能使用static_cast将指向指针的指针转换为void**:您需要reinterpret_cast
In code:
在代码:
#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) );
However, static_cast
works for simple pointers (not pointers to pointers), so the above code can be rewritten to avoid reinterpret_cast
(at a price of an extra variable) in the following way:
但是,static_cast可以用于简单的指针(而不是指针),因此可以重写上面的代码,以避免以以下方式重新解释t_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);
#1
2187
static_cast
is the first cast you should attempt to use. It does things like implicit conversions between types (such as int
to float
, or pointer to void*
), and it can also call explicit conversion functions (or implicit ones). In many cases, explicitly stating static_cast
isn't necessary, but it's important to note that the T(something)
syntax is equivalent to (T)something
and should be avoided (more on that later). A T(something, something_else)
is safe, however, and guaranteed to call the constructor.
static_cast是您应该尝试使用的第一个强制类型转换。它在类型之间进行隐式转换(比如int to float,或者指针to void*),还可以调用显式转换函数(或隐式转换函数)。在许多情况下,显式地声明static_cast不是必需的,但是需要注意的是,T(某物)语法等同于(T)某物,应该避免(稍后详细讨论)。然而,T(something, something_else)是安全的,并且保证调用构造函数。
static_cast
can also cast through inheritance hierarchies. It is unnecessary when casting upwards (towards a base class), but when casting downwards it can be used as long as it doesn't cast through virtual
inheritance. It does not do checking, however, and it is undefined behavior to static_cast
down a hierarchy to a type that isn't actually the type of the object.
static_cast也可以通过继承层次结构进行强制转换。向上抛出(指向基类)是不必要的,但向下抛出时,只要不通过虚继承就可以使用。但是,它不进行检查,并且static_cast一个层次结构到一个实际上不是对象类型的类型是未定义的行为。
const_cast
can be used to remove or add const
to a variable; no other C++ cast is capable of removing it (not even reinterpret_cast
). It is important to note that modifying a formerly const
value is only undefined if the original variable is const
; if you use it to take the const
off a reference to something that wasn't declared with const
, it is safe. This can be useful when overloading member functions based on const
, for instance. It can also be used to add const
to an object, such as to call a member function overload.
const_cast可用于删除或向变量添加const;没有其他c++强制转换能够删除它(甚至不能重新解释强制转换)。需要注意的是,只有当原始变量为const时,修改以前的const值才是未定义的;如果你用它来指代那些与const没有声明的东西,它是安全的。例如,当基于const的重载成员函数时,这一点很有用。它还可以用于向对象添加const,例如调用成员函数重载。
const_cast
also works similarly on volatile
, though that's less common.
const_cast在volatile上也有类似的工作,不过这种情况并不常见。
dynamic_cast
is almost exclusively used for handling polymorphism. You can cast a pointer or reference to any polymorphic type to any other class type (a polymorphic type has at least one virtual function, declared or inherited). You can use it for more than just casting downwards -- you can cast sideways or even up another chain. The dynamic_cast
will seek out the desired object and return it if possible. If it can't, it will return nullptr
in the case of a pointer, or throw std::bad_cast
in the case of a reference.
dynamic_cast几乎只用于处理多态性。您可以将任何多态类型的指针或引用投射到任何其他类类型(多态类型至少有一个虚拟函数,声明或继承)。你可以使用它不仅仅是向下投射——你可以向一边投射,甚至向上投射另一条链条。dynamic_cast将查找所需的对象并在可能的情况下返回它。如果不能,它将在指针的情况下返回nullptr,或者在引用时抛出std::bad_cast。
dynamic_cast
has some limitations, though. It doesn't work if there are multiple objects of the same type in the inheritance hierarchy (the so-called 'dreaded diamond') and you aren't using virtual
inheritance. It also can only go through public inheritance - it will always fail to travel through protected
or private
inheritance. This is rarely an issue, however, as such forms of inheritance are rare.
然而,dynamic_cast有一些局限性。如果继承层次结构中有相同类型的多个对象(所谓的“可怕的钻石”),并且您没有使用虚拟继承,那么它就不起作用了。它也只能通过公共继承——它将永远不能通过受保护的或私有继承。然而,这很少是一个问题,因为这种继承形式很少见。
reinterpret_cast
is the most dangerous cast, and should be used very sparingly. It turns one type directly into another - such as casting the value from one pointer to another, or storing a pointer in an int
, or all sorts of other nasty things. Largely, the only guarantee you get with reinterpret_cast
is that normally if you cast the result back to the original type, you will get the exact same value (but not if the intermediate type is smaller than the original type). There are a number of conversions that reinterpret_cast
cannot do, too. It's used primarily for particularly weird conversions and bit manipulations, like turning a raw data stream into actual data, or storing data in the low bits of an aligned pointer.
reinterpret_cast是最危险的cast,应该非常谨慎地使用它。它将一种类型直接转换为另一种类型,比如将值从一个指针转换到另一个指针,或者将指针存储在int中,或者其他各种令人讨厌的东西。在很大程度上,只有当您将结果返回到原始类型时,您才能得到的唯一保证是,您将得到完全相同的值(但如果中间类型小于原始类型的话)。有许多转换是reinterpret_cast不能做的。它主要用于特别奇怪的转换和位操作,如将原始数据流转换为实际数据,或将数据存储在对齐指针的低位。
C-style cast and function-style cast are casts using (type)object
or type(object)
, respectively. A C-style cast is defined as the first of the following which succeeds:
c样式强制转换和函数样式强制转换分别使用(类型)对象或类型(对象)。c型铸造被定义为以下第一个成功的铸造:
const_cast
- const_cast
-
static_cast
(though ignoring access restrictions) - static_cast(尽管忽略访问限制)
-
static_cast
(see above), thenconst_cast
- static_cast(见上面),然后是const_cast。
reinterpret_cast
- reinterpret_cast
-
reinterpret_cast
, thenconst_cast
- reinterpret_cast,然后const_cast
It can therefore be used as a replacement for other casts in some instances, but can be extremely dangerous because of the ability to devolve into a reinterpret_cast
, and the latter should be preferred when explicit casting is needed, unless you are sure static_cast
will succeed or reinterpret_cast
will fail. Even then, consider the longer, more explicit option.
因此,在某些情况下,它可以作为其他类型转换的替代,但是由于可以将其转换为reviewt_cast,因此可能非常危险,而在需要显式转换时,应该首选后者,除非您确信static_cast将成功或重新解释t_cast将失败。即便如此,也要考虑更长的、更明确的选择。
C-style casts also ignore access control when performing a static_cast
, which means that they have the ability to perform an operation that no other cast can. This is mostly a kludge, though, and in my mind is just another reason to avoid C-style casts.
c样式的强制转换在执行static_cast时也忽略了访问控制,这意味着它们可以执行其他强制转换无法执行的操作。不过,在我看来,这主要是一种拼凑的东西,这只是避免使用c风格的数据类型转换的另一个原因。
#2
276
Use dynamic_cast
for converting pointers/references within an inheritance hierarchy.
使用dynamic_cast在继承层次结构中转换指针/引用。
Use static_cast
for ordinary type conversions.
对于普通类型转换,使用static_cast。
Use reinterpret_cast
for low-level reinterpreting of bit patterns. Use with extreme caution.
使用reinterpretation t_cast对位模式进行低级的重新解释。使用极端谨慎。
Use const_cast
for casting away const/volatile
. Avoid this unless you are stuck using a const-incorrect API.
使用const_cast来丢弃const/volatile。避免这种情况,除非您使用了不正确的API。
#3
147
(A lot of theoretical and conceptual explanation has been given above)
(以上给出了很多理论和概念上的解释)
Below are some of the practical examples when I used static_cast, dynamic_cast, const_cast, reinterpret_cast.
下面是一些实际的例子,我使用static_cast、dynamic_cast、const_cast、reviewt_cast。
(Also referes this to understand the explaination : http://www.cplusplus.com/doc/tutorial/typecasting/)
(这也可以用来理解解释:http://www.cplusplus.com/doc/tutorial/typecasting/)
static_cast :
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 :
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 :
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 :
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);
}
#4
48
It might help if you know little bit of internals...
如果你了解一些内部因素,可能会有所帮助。
static_cast
static_cast
- C++ compiler already knows how to convert scaler types such as float to int. Use static_cast for them.
- c++编译器已经知道如何转换标量类型,例如float到int。使用static_cast。
- In general, while converting type A to B, static_cast would call B's constructor passing it A. If B doesn't have such constructor then you get compile time error.
- 一般来说,当将类型A转换为B时,static_cast会调用B的构造函数传递A。如果B没有这样的构造函数,那么就会出现编译时间错误。
- Cast from
A*
toB*
always succeeds if A and B are in inheritance hierarchy (or void) otherwise you get compile error. - 如果A和B处于继承层次结构(或void)中,则从A*强制转换为B*总是成功的,否则会导致编译错误。
- Gotcha: If you cast base pointer to derived pointer but if actual object is if not derived type then you don't get error. You get bad pointer and as soon as you try to access members of derived pointer, you get segfault at runtime.
- 如果你将基指针转换成派生指针,但如果实际对象不是派生类型,那么你不会得到错误。当你试图访问派生指针的成员时,你会得到一个坏指针,你会在运行时得到segfault。
- Same goes for
A&
toB&
. - a&b也是一样。
- Gotcha: Cast from Derived to Base or viceversa creates new copy! For people coming from C#/Java, many of above can be a huge surprise.
- 捕获:从派生到基或viceversa创建新副本!对于来自c# /Java的人来说,上面的许多内容可能是一个巨大的惊喜。
dynamic_cast
dynamic_cast
- dynamic_cast uses runtime type information to figure out if cast is valid. For example,
(Base*)
to(Derived*)
may fail if pointer is not actually of derived type. - dynamic_cast使用运行时类型信息来确定cast是否有效。例如,如果指针实际上不是派生类型,则(Base*)到(派生*)可能会失败。
- This means, dynamic_cast is very expensive compared to static_cast!
- 这意味着,与static_cast相比,dynamic_cast非常昂贵!
- For
A*
toB*
, if cast is invalid then dynamic_cast will return nullptr. - 对于A*到B*,如果强制转换无效,那么dynamic_cast将返回nullptr。
- For
A&
toB&
if cast is invalid then dynamic_cast will throw bad_cast exception. - 对于a&to b&if强制转换无效,那么dynamic_cast将抛出bad_cast异常。
const_cast
const_cast
- While static_cast can do non-const to const it can't go other way around. The const_cast can do both ways.
- 虽然static_cast可以执行非const命令,但它不能执行其他方式。const_cast可以有两种方式。
- One example where this comes handy is iterating through some container like
set<T>
which only returns its elements as const to make sure you don't change its key. However if your intent is to modify object's non-key members then it should be ok. You can use const_cast to remove constness. -
这很方便的一个例子是迭代某个容器,比如set
,它只返回其元素const,以确保不更改其键。但是,如果您的意图是修改对象的非关键成员,那么它应该是可以的。您可以使用const_cast来消除一致性。 - Another example is when you want to implement
T& foo()
as well asconst T& foo()
. To avoid code duplication, you can apply const_cast to return value of one function from another. - 另一个例子是当您希望实现t&foo()以及const t&foo()时。为了避免代码重复,可以应用const_cast从另一个函数返回值。
- Unlike above two casts, there is runtime overhead.
- 与上面两个类型不同,这里有运行时开销。
reinterpret_cast
reinterpret_cast
- This basically says that take these bytes at this memory location and think of it as given object.
- 这基本上是说,在这个内存位置取这些字节并把它想象成给定的对象。
- For example, you can load 4 bytes of float to 4 bytes of int to see how bits in float looks like.
- 例如,您可以加载4字节的浮点数到4字节的int数,以了解浮点数中的位数是什么样子的。
- Obviously, if data is not correct for the type, you may get segfault.
- 显然,如果数据对类型不正确,您可能会得到segfault。
- There is no runtime overhead for this cast.
- 这个转换没有运行时开销。
#5
11
Does this answer your question?
这能回答你的问题吗?
I have never used reinterpret_cast
, and wonder whether running into a case that needs it isn't a smell of bad design. In the code base I work on dynamic_cast
is used a lot. The difference with static_cast
is that a dynamic_cast
does runtime checking which may (safer) or may not (more overhead) be what you want (see msdn).
我从来没有使用过reinterpret_cast,我想知道遇到一个需要它的案例是否有不好的设计味道。在我的代码库中,经常使用dynamic_cast。与static_cast不同的是,dynamic_cast执行的运行时检查可能(更安全),也可能(更多开销)是您想要的(请参阅msdn)。
#6
9
In addition to the other answers so far, here is unobvious example where static_cast
is not sufficient so that reinterpret_cast
is needed. Suppose there is a function which in an output parameter returns pointers to objects of different classes (which do not share a common base class). A real example of such function is CoCreateInstance()
(see the last parameter, which is in fact void**
). Suppose you request particular class of object from this function, so you know in advance the type for the pointer (which you often do for COM objects). In this case you cannot cast pointer to your pointer into void**
with static_cast
: you need reinterpret_cast<void**>(&yourPointer)
.
除了到目前为止的其他答案之外,这里还有一个不明显的示例,说明static_cast不够,因此需要reinterpret_cast。假设有一个函数,它在输出参数中返回指向不同类的对象的指针(它们不共享公共基类)。此类函数的一个真实示例是CoCreateInstance()(请参阅最后一个参数,它实际上是void**)。假设您从这个函数中请求特定的对象类,以便预先知道指针的类型(通常对COM对象这样做)。在这种情况下,您不能使用static_cast将指向指针的指针转换为void**:您需要reinterpret_cast
In code:
在代码:
#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) );
However, static_cast
works for simple pointers (not pointers to pointers), so the above code can be rewritten to avoid reinterpret_cast
(at a price of an extra variable) in the following way:
但是,static_cast可以用于简单的指针(而不是指针),因此可以重写上面的代码,以避免以以下方式重新解释t_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);