static_cast 订阅
static_cast是一个c++运算符，功能是把一个表达式转换为某种类型，但没有运行时类型检查来保证转换的安全性。 展开全文
static_cast是一个c++运算符，功能是把一个表达式转换为某种类型，但没有运行时类型检查来保证转换的安全性。

C++ static_cast

static_cast
static_cast用法
static_cast ( expression )

• 1.static_cast对类的指针只能转换有继承关系的类。对普通的指针来说只能在void*和其他指针之间转换。它还可转换简单的类型，比如int到char等。不能提供数字到指针的转换。不能提供不同类型指针之间的转换比如int*到...
• 标准C++的类型转换符：static_cast、dynamic_cast、reinterpret_cast和const_cast
• 呵呵，今天来好好看看着几个转换操作符的用法。以前老是看着眼熟，但是用着手生。今天决定搞定这些个东西。在C语言中类型转换有几种方式：1.(expression).在表达式外边加括号，由编译器来决定怎么改变。...
• 前言 这篇文章总结的是C++中的类型转换，这些小的知识点，有的时候，自己不是很注意，但是在实际开发中确实经常使用的。俗话说的好，不懂自己写的代码的程序员，不是好的...在标准C++中有四个类型转换符：static_cast
• 本文用示例讲解了dynamic_caststatic_cast子类与基类之间转换功能的使用方法
• 1、static_cast static_cast Operator The expression static_cast < type-id > ( expression ) converts expression to the type of type-id based solely on the types present in the expression. ...
C++中的四种操作符形式类型转换
1、static_cast （静态类型转换）
主要使用场景：适用于将void*转换为其他的指针
int a = 100;
void* pv = &a;
//int *pi = pv;  //不能隐式转换，只能显示转换
int *pi = static_case<int *>(pv);
*pi = 50;
cout << a << endl;  // 可以看到输出结果为50
思考：如果如果指针或引用指向的已经是const属性内存空间（只读），使用static_cast转换呢？
const int a = 100;
void* pv = &a;
//int *pi = pv;     //不能隐式转换，只能显示转换
int *pi = static_case<int *>(pv);
*pi = 50;           // 此处不会报错
cout << a << endl;  // 但输出结果为100。因为内存为变量a分配的空间为只读

==》MSDN

static_cast Operator

The expression static_cast <
type-id > (
expression ) converts
expression to the type of
type-id

based solely on the types present in the expression. No run-time type check is made to ensure

the safety of the conversion.

// static_cast 转换的类型 由 <type_id>的类型决定, 在转换过程中不进行运行时类型识别以保证转换的安全性

Syntax

static_cast <
type-id > (
expression )

The static_cast operator can be used for operations such as converting a pointer to a base class

to a pointer to a derived class. Such conversions are not always safe. For example:

class B { ... };

class D : public B { ... };

void f(B* pb, D* pd)

{

D* pd2 = static_cast<D*>(pb); // not safe, pb may point to just B 这种基类指针转子类对象指针的方式（我们通常称为“向上转换”或者“向上造型”），通常采用dynamic_cast 以保证安全性

B* pb2 = static_cast<B*>(pd); // safe conversion  子类转基类则是安全的

...

}

In contrast to dynamic_cast, no run-time check is made on the static_cast conversion of pb.

The object pointed to by pb may not be an object of type D, in which case the use of *pd2 could

be disastrous. For instance, calling a function that is a member of the D class, but not the B

class, could result in an access violation.

The dynamic_cast and static_cast operators move a pointer throughout a class hierarchy.

However, static_cast relies exclusively on the information provided in the cast statement and

can therefore be unsafe. For example:

class B { ... };

class D : public B { ... };

void f(B* pb)

{

D* pd1 = dynamic_cast<D*>(pb);

D* pd2 = static_cast<D*>(pb);

}

If pb really points to an object of type D, then pd1 and pd2 will get the same value. They will

also get the same value if pb == 0.

If pb points to an object of type B and not to the complete D class, then dynamic_cast will know

enough to return zero. However, static_cast relies on the programmer’s assertion that pb points

to an object of type D and simply returns a pointer to that supposed D object.

Consequently, static_cast can do the inverse of implicit conversions, in which case the results

are undefined. It is left to the programmer to ensure that the results of a static_cast conversion

are safe.

This behavior also applies to types other than class types. For instance, static_cast can be used

to convert from an int to a char. However, the resulting char may not have enough bits to hold

the entire int value. Again, it is left to the programmer to ensure that the results of static_cast

conversion are safe.

The static_cast operator can also be used to perform any implicit conversion, including standard

conversions and user-defined conversions. For example:

typedef unsigned char BYTE

void f()

{

char ch;

int i = 65;

float f = 2.5;

double dbl;

ch = static_cast<char>(i); // int to char

dbl = static_cast<double>(f); // float to double

...

i = static_cast<BYTE>(ch);

...

}

The static_cast operator can explicitly convert an integral value to an enumeration type. If the

value of the integral type does not fall within the range of enumeration values, the resulting

enumeration value is undefined.

The static_cast operator converts a null pointer value to the null pointer value of the destination

type.

Any expression can be explicitly converted to type void by the static_cast operator. The

destination void type can optionally include the const, volatile, or __unaligned attribute.

The static_cast operator cannot cast away the const, volatile, or __unaligned attributes. See

const_cast Operator for information on removing these attributes.

通过上面MSDN的说明文档，我们可以知道，表达式static_cast < type-id > ( expression ) 用于进行类型的转换，但是不会进行运行时类型识别，因此使用他并不总是安全的，要注意使用场景
2、dynamic_cast（动态类型转换）
dynamic_cast 类型转换的适用场景： 主要用于具有父子类关系的，父类对象指针（或引用）转换成子类对象指针（或者引用）（“向上转换”）的场景

dynamic_cast Operator
The expression dynamic_cast<type-id>( expression ) converts the operand expression to an object of type type-id. The type-id must be a pointer or a reference to a previously defined class type or a “pointer to void”. The type of expression must be a pointer if type-id is a pointer, or an l-value if type-id is a reference.
Syntax
dynamic_cast < type-id > ( expression )
If type-id is a pointer to an unambiguous accessible direct or indirect base class of expression, a pointer to the unique subobject of type type-id is the result. For example:
class B { ... };
class C : public B { ... };
class D : public C { ... };

void f(D* pd)
{
C* pc = dynamic_cast<C*>(pd);   // ok: C is a direct base class
// pc points to C subobject of pd

B* pb = dynamic_cast<B*>(pd);   // ok: B is an indirect base class
// pb points to B subobject of pd
...
}

This type of conversion is called an “upcast” because it moves a pointer up a class hierarchy, from a derived class to a class it is derived from. An upcast is an implicit conversion.
If type-id is void*, a run-time check is made to determine the actual type of expression. The result is a pointer to the complete object pointed to by expression. For example:
class A { ... };

class B { ... };

void f()
{
A* pa = new A;
B* pb = new B;
void* pv = dynamic_cast<void*>(pa);
// pv now points to an object of type A
...
pv = dynamic_cast<void*>(pb);
// pv now points to an object of type B
}

If type-id is not void*, a run-time check is made to see if the object pointed to by expression can be converted to the type pointed to by type-id.
If the type of expression is a base class of the type of type-id, a run-time check is made to see if expression actually points to a complete object of the type of type-id. If this is true, the result is a pointer to a complete object of the type of type-id. For example:
class B { ... };
class D : public B { ... };

void f()
{
B* pb = new D;               // unclear but ok
B* pb2 = new B;

D* pd = dynamic_cast<D*>(pb);      // ok: pb actually points to a D
...
D* pd2 = dynamic_cast<D*>(pb2);   //error: pb2 points to a B, not a D
// pd2 == NULL
...
}

This type of conversion is called a “downcast” because it moves a pointer down a class hierarchy, from a given class to a class derived from it.
In cases of multiple inheritance, possibilities for ambiguity are introduced. Consider the class hierarchy shown in Figure 4.5:
Figure 4.5   Class Hierarchy Showing Multiple Inheritance

A pointer to an object of type D can be safely cast to B or C. However, if D is cast to point to an A object, which instance of A would result? This would result in an ambiguous casting error. To get around this problem, you can perform two unambiguous casts. For example:
void f()
{
D* pd = new D;
A* pa = dynamic_cast<A*>(pd);      // error: ambiguous
B* pb = dynamic_cast<B*>(pd);      // first cast to B
A* pa2 = dynamic_cast<A*>(pb);   // ok: unambiguous
}

Further ambiguities can be introduced when you use virtual base classes. Consider the class hierarchy shown in Figure 4.6:
Figure 4.6   Class Hierarchy Showing Virtual Base Classes

In this hierarchy, A is a virtual base class. See Virtual Base Classes for the definition of a virtual base class. Given an instance of class E and a pointer to the A subobject, a dynamic_cast to a pointer to B will fail due to ambiguity. You must first cast back to the complete E object, then work your way back up the hierarchy, in an unambiguous manner, to reach the correct B object.
Consider the class hierarchy shown in Figure 4.7:
Figure 4.7   Class Hierarchy Showing Duplicate Base Classes

Given an object of type E and a pointer to the D subobject, to navigate from the D subobject to the left-most A subobject, three conversions can be made. You can perform a dynamic_cast conversion from the D pointer to an E pointer, then a conversion (either dynamic_cast or an implicit conversion) from E to B, and finally an implicit conversion from B to A. For example:
void f(D* pd)
{
E* pe = dynamic_cast<E*>(pd);
B* pb = pe;      // upcast, implicit conversion
A* pa = pb;      // upcast, implicit conversion
}

The dynamic_cast operator can also be used to perform a “cross cast.” Using the same class hierarchy, it is possible to cast a pointer, for example, from the B subobject to the D subobject, as long as the complete object is of type E.
Considering cross casts, it is actually possible to do the conversion from a pointer to D to a pointer to the left-most A subobject in just two steps. You can perform a cross cast from D to B, then an implicit conversion from B to A. For example:
void f(D* pd)
{
B* pb = dynamic_cast<B*>(pd);      // cross cast
A* pa = pb;                  // upcast, implicit conversion
}

A null pointer value is converted to the null pointer value of the destination type by dynamic_cast.
When you use dynamic_cast < type-id > ( expression ), if expression cannot be safely converted to type type-id, the run-time check causes the cast to fail. For example:
class A { ... };

class B { ... };

void f()
{
A* pa = new A;
B* pb = dynamic_cast<B*>(pa);      // fails, not safe;
// B not derived from A
...
}

The value of a failed cast to pointer type is the null pointer. A failed cast to reference type throws a bad_cast exception.

Send feedback to MSDN.Look here for MSDN Online resources.

3、const_cast（常类型转换）
使用场景：主要用于去除一个指针或引用的常属性
 const int a =10;
const int *pa =&a;
*pa = 20;//error
int *p2 =const_cast<int *>(pa);
*p2 = 20;//ok

==》MSDN
const_cast Operator
The const_cast operator can be used to remove the const, volatile, and __unaligned attribute(s) from a class.
Syntax
const_cast < type-id > ( expression )
A pointer to any object type or a pointer to a data member can be explicitly converted to a type that is identical except for the const, volatile, and __unaligned qualifiers. For pointers and references, the result will refer to the original object. For pointers to data members, the result will refer to the same member as the original (uncast) pointer to data member. Depending on the type of the referenced object, a write operation through the resulting pointer, reference, or pointer to data member might produce undefined behavior.
The const_cast operator converts a null pointer value to the null pointer value of the destination type.

Send feedback to MSDN.Look here for MSDN Online resources.

4、reinterpret_cast（重解释类型转换）
主要使用场景：
1、在指针和整型数之间的转换 2、任意的指针或引用之间的转换
3、以上三个操作符都无法完成的类型转换，可使用reinterpret_cast重解释类型转换

Operation: reinterpret_cast
Robert Schmidt Microsoft Corporation
June 1, 2000
Last time I discussed the conversion operator static_cast. This time, I cover the companion operator reinterpret_cast, and give some guidance on when to use each.
While the Standard gives static_cast a sweeping general property plus a complicated set of exceptions, it limits reinterpret_cast to two fundamental roles:
Conversions to and from pointers  Overlaying an lvalue with multiple types (a.k.a. type punning)
As its name suggests, this style of cast reinterprets its operand's representation as having the target type. This reinterpretation involves no calls to conversion constructors or conversion operators; indeed, a reinterpret_cast may leave the operand's bit pattern intact, so that the conversion is purely a compile-time act with no run-time consequences.
Pointer Conversions
The set of pointer-specific conversions allowed by reinterpret_cast is fairly narrow:
From a pointer to an integer type.  From an integer or enumeration type to a pointer.  Among pointers to objects, functions, or members.
Provided that object-size and alignment guarantees are met (as I'll discuss below), the circular conversion sequence
T1 x1;
T2 x2;

x2 = reinterpret_cast<T2>(x1);
x1 = reinterpret_cast<T1>(x2);

restores x1's original value. Beyond this guarantee, conversion effects are not specified. In particular, conversions might change the underlying bit representation of the converted value, or they might leave the bit pattern intact. In the case of the latter, a reinterpret_cast truly represents a reinterpretation—but not an actual change—of an expression's bit pattern.
That all of these conversions involve pointers should not surprise you. On a given machine, the underlying representation among kindred pointers is often identical. Pointers, therefore, offer an ideal opportunity for static type conversions that don't actually require a run-time modification.
Like static_cast, reinterpret_cast cannot remove cv-qualification. The C++ committee members clearly want you to use const_cast for such conversions.
Converting Pointers To/From Non-Pointers
For a pointer to convert to an integer type, that integer type must be large enough to hold the pointer's value. The actual conversion is implementation-defined, although as the Standard notes, the conversion "is intended to be unsurprising to those who know the addressing structure of the underlying machine."
Going the other way, a value of integer or enumeration type can convert to a pointer. Further, a pointer converted to an integer and back will retain its original value—assuming the integer is large enough to hold the pointer. Otherwise, the mapping is implementation-defined.
(For those living in the Wonderful World of Windows, these are the rules that let you convert pointers to DWORDs and back again with impunity.)
One special value is the null pointer constant, which is implemented as an integer constant expression of value zero. Null pointer constants always convert to a null pointer of the target type. In a subtle distinction, other integer expressions of value zero may or may not convert to a null pointer:
#define NULL 0

const int i1 = 0;
int i2 = 0;

reinterpret_cast<void *>(NULL);  // yields null pointer
reinterpret_cast<void *>(i1);    // yields null pointer
reinterpret_cast<void *>(i2);    // may or may not yield null pointer

Converting Among Pointers
Pointers to the same "kind" of entity—object, function, member object, or member function—can convert to one another, with the following caveats and restrictions:
As usual, the destination type cannot be less cv-qualified than the original type.  When converting among pointers to objects or member objects, the destination object type cannot have stricter alignment requirements than the original object type.  Null pointer values of the original type are converted to null pointer values of the destination type.
The following incomplete program shows examples of each conversion kind:
class T1;
class T2;

//
//  pointer to object
//
typedef T1 *O1;
typedef T2 *O2;

O1 o1;
reinterpret_cast<O2>(o1);

//
//  pointer to function
//
typedef T1 (*F1)();
typedef T2 (*F2)();

F1 f1;
reinterpret_cast<F2>(f1);

//
//  pointer to member object
//
typedef int  T1:: *MO1;
typedef long T2:: *MO2;

MO1 mo1;
reinterpret_cast<MO2>(mo1);

//
//  pointer to member function
//
typedef void (T1:: *MF1)();
typedef void (T2:: *MF2)();

MF1 mf1;
reinterpret_cast<MF2>(mf1); // OK

Based on my reading of both the C99 and C++ Standards, pointers of different kinds cannot convert to one another. Assuming I'm right, the conversions
reinterpret_cast<F1>(o1);
reinterpret_cast<O1>(f1);

should not compile. However, all of the translators I've tried—including EDG's in strict mode—allow these conversions. Fortunately, these non-Standard conversions appear to be pure extensions, meaning programs that don't use them aren't affected by them.
If you use such cross-kind pointer conversions, be aware that your code is non-conformant and thus non-portable. (Although if every compiler you care about supports this extension, then your code is portable in practice.)
Type Overlays
In addition to the pointer conversions I've shown above, reinterpret_cast also lets you overlay an lvalue with an arbitrary type interpretation. Specifically, you can bind a T1 lvalue to a T2 reference if you can reinterpret a T1 address as a T2 address. Given the declaration
T1 x1;

the cast
reinterpret_cast<T2 &>(x1);

is allowed if the conversion
reinterpret_cast<T2 *>(&x1);

is also allowed (assuming that & and * represent the built-in operators).
The reference cast is tantamount to dereferencing the pointer cast, so that
reinterpret_cast<T2 &>(x1)

and
*reinterpret_cast<T2 *>(&x1)

are equivalent. You can think of
reinterpret_cast<T2 &>(x1);

as &x1 being reinterpreted as a T2 *, then dereferenced into a T2 lvalue—even though the syntax suggests that x1 is directly reinterpreted as a T2 lvalue. This correlation between pointers and references shouldn't surprise you, since references are typically implemented as pointers under the hood. If a compiler allows a conversion to a T2 *, it can reinterpret that T2 * as its collateral T2 &, since the T2 * and T2 & probably share the same representation.
Because the cast operator doesn't directly reinterpret its operand's representation, I find the name reinterpret_cast to be somewhat misleading here. (Compare this cast to the earlier pointer-conversion examples, where the operand's representation was literally being reinterpreted.) When the C++ committee members "overloaded" reinterpret_cast, they took advantage of an implementation symbiosis: The underlying pointer-reinterpretation mechanism happens to permit reference-reinterpretation as well, even though the concepts are logically distinct. Whether they ought to have taken that advantage, in lieu of creating a fifth conversion operator or banning type puns outright, is another matter.
Unlike the other examples of reinterpret_cast, the T2 & conversion does not require that T1 and T2 preserve their values during a circular conversion, or that they even be convertible at all. Indeed, only pointers to those types must be convertible. Furthermore, since the T2 & binds directly to the original x1 object, no temporaries or other objects are created, and no conversion operators or constructors are called.
Punning
Programmers often call this casting technique "type punning." Like English puns, type puns allow multiple meanings for the same entity. In this way, punning is analogous to polymorphism, with two crucial differences:
Polymorphic types must have an inheritance relationship. Punned types can be completely unrelated, even incongruous.  Polymorphism relies on run-time object identification and conversion, which can induce significant run-time space and speed cost. Punning has minimal or no run-time cost. (The only potential cost is that of a pointer-to-pointer conversion; depending on the implementation, such a conversion may require no run-time resource.)
Unions are actually a closer analogy, since both unions and puns
Overlay an arbitrary set of types atop the same storage  Let you set the storage as one type, and reference it as another  Bypass the language's type-conversion rules (and risk undefined behavior)
To understand this analogy more clearly, ponder the effects of both
union
{
T1 x1;
T2 x2;
// ...
Tn xn;
} u;

u.x1; // treats the object as if it had type T1
u.x2; // treats the object as if it had type T2
// ...
u.xn; // treats the object as if it had type Tn

and
T1  x1;
T2 &x2 = reinterpret_cast<T2 &>(x1);
// ...
Tn &xn = reinterpret_cast<Tn &>(x1);

x1;   // treats the object as if it had type T1
x2;   // treats the object as if it had type T2
// ...
xn;   // treats the object as if it had type Tn

Punning Consequences
Punning lets you glue as many differently typed faces as you want onto the same object. For the technique to be maximally effective, you must understand the consequences of treating an object as if it were really of another type. Consider the example
#include <iostream>
using namespace std;

int main()
{
unsigned long   x1 = 0x12345678;
unsigned short &x2 = reinterpret_cast<unsigned short &>(x1);
cout << hex << x1 << endl;
cout << hex << x2 << endl;
x2 = 0xABCD;
cout << hex << x1 << endl;
cout << hex << x2 << endl;
}

When run with Visual C++, this program produces
12345678
1234
abcd5678
abcd

Because the actual x1 object is bigger than what x2 believes it references, accesses through x2 "see" only part of x1. Similarly, changes through x2 overwrite part—but not all—of x1. The program is therefore safe, since x2's access stays within x1's bounds.
Now switch the definitions, so that the actual x1 object's type is too short. The modified program becomes
#include <iostream>
using namespace std;

int main()
{
unsigned short  x1 = 0x1234;
unsigned long  &x2 = reinterpret_cast<unsigned long &>(x1);
cout << hex << x1 << endl;
cout << hex << x2 << endl;
x2 = 0xABCDEFAB;
cout << hex << x1 << endl;
cout << hex << x2 << endl;
}

The new results, at least on my machine, are
1234
12340003
abcd
abcdefab

x1 is now smaller than what x2 thinks it's bound to. As a result, access through x2 fetches memory beyond x1's borders; on my machine, that extra non-x1 memory shows up as 0x0003. The corresponding assignment through x2 scribbles beyond the limits of the x1 object. The result is undefined program behavior. In my case, the program didn't bomb; your mileage may vary.
Comparison and Contrast
Although I have yet to formally describe const_cast and dynamic_cast, I'll still include them in my (somewhat imprecise) rules of thumb for conversion operators:
If you reduce cv-qualification, use const_cast.  If you downcast, and want run-time assurance that the cast is valid, use dynamic_cast.  If you reinterpret a bit pattern, and a pointer is involved, use reinterpret_cast.  If you engage in type punning, use reinterpret_cast.  For all other conversions, use static_cast.  Avoid C casts of the form (T) e and functional casts of the form T(e). The conversion operators are both more obvious and more precise.
General Run-Time Behavior
reinterpret_cast traffics only in integers, enumerations, pointers, and references. It doesn't call user-defined functions, and probably doesn't call into the run-time library. At worst, a pointer conversion might require a few machine instructions to widen or narrow its operand. (While a compiler may package these conversions in library routines, I don't know of a compiler that actually does so.)
In contrast, static_cast converts among all of the above as well as floating-point and class types. Its run-time behavior is very much tied to the types being converted. For example, the conversion
int i;
static_cast<X>(i);

has several possible effects, depending on the type of X:
If X is a pointer, integer, or enumeration, the effect is tantamount to a reinterpret_cast.  If X is a floating-point type, i is converted to X. Depending on the implementation, this conversion may require inline floating-point instructions, calls to floating-point library routines, or hand-off to a separate floating-point processor.  If X is a class, i is the argument to a suitable X constructor, which must be declared and accessible.
Overlap
There is some overlap in the behavior of reinterpret_cast and static_cast. Both forms
Convert between void * and other pointer types  Convert between base and derived pointers  Bind a derived reference to a base object
Where either form will work, I recommend you stick with reinterpet_cast:
The name reinterpret_cast more precisely describes the transformation.  static_cast is one of the most dangerous tools in the C++ shed. You should reach for it only when nothing else will work.
I wish the committee had partitioned reintepret_cast and static_cast into mutually exclusive behavior sets. If the two operators had no intersection, I believe programmers could better understand when to use each. As things stand now, I suspect many programmers guess which to use, and let the compiler judge that choice.
Prevented Overlap
Conversely, there are behaviors that you might expect to overlap that don't. Consider the conversion
long l;
int i;

i = static_cast<int>(l);

With Visual C++ targeting Win32, long and int have identical representations. The conversion from long to int is really a reinterpretation of the existing long value. Indeed, the circular conversion
i = static_cast<int>(l);
l = static_cast<long>(i);

restores the original l value, thereby matching a key guarantee of reinterpret_cast.
You might consequently expect that
i = reinterpret_cast<int>(l);
should work as well, and that
i = reinterpret_cast<int>(l);
l = reinterpret_cast<int>(i);

should restore l's value. However, the language rules prevent these reinterpret_casts—even though they would have the same implementation as the static_casts.
The rules are not capricious. While the long-to-int conversion is a physical reinterpretation on Win32, it is not such a reinterpretation on all platforms. For example, Win16's ints and longs have different sizes. On that architecture, the conversion can change the long's value, so that a circular conversion might not restore the original value.
Bon Voyage
While I have yet to pin down my next column topic, I suspect I'm about to suffer great inspiration. The piece you're reading now is scheduled to go "live" on June 1. A few days after that, I'll be in Oregon attending Scott Meyers' STL seminar. I'm sure that trip will give me much to write about. (Reading through Scott's course materials, I've already jotted down enough ideas to cover me for months.)
Robert Schmidt is a technical writer for MSDN. His other major writing distraction is the C/C++ Users Journal, for which he is a contributing editor and columnist. In previous career incarnations he's been a radio DJ, wild-animal curator, astronomer, pool-hall operator, private investigator, newspaper carrier, and college tutor.
Deep C++ Glossary

Send feedback to MSDN.Look here for MSDN Online resources.

展开全文
• 显式类型转换-被称为“强制类型转换”(cast) C 风格： (type-id) C++风格： static_cast、dynamic_cast、reinterpret_cast、和const_cast.. 关于强制类型转换的问题，很多书都讨论过，写的最详细的是C++ 之父的...


首先回顾一下C++类型转换：
C++类型转换分为：隐式类型转换和显式类型转换
第1部分. 隐式类型转换-又称为“标准转换”
包括以下几种情况：
1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。
int ival = 3;
double dval = 3.14159;

ival + dval;//ival被提升为double类型
2)一种类型表达式赋值给另一种类型的对象：目标类型是被赋值对象的类型
​
int *pi = 0; // 0被转化为int *类型

ival = dval; // double->int

​
例外：void指针赋值给其他指定类型指针时，不存在标准转换，编译出错
3)将一个表达式作为实参传递给函数调用，此时形参和实参类型不一致：目标转换类型为形参的类型
extern double sqrt(double);

cout << "The square root of 2 is " << sqrt(2) << endl;
//2被提升为double类型：2.0
4)从一个函数返回一个表达式，表达式类型与返回类型不一致：目标转换类型为函数的返回类型
double difference(int ival1, int ival2)
{
return ival1 - ival2;
//返回值被提升为double类型
}
第2部分. 显式类型转换-被称为“强制类型转换”(cast)
C     风格： (type-id)        C++风格： static_cast、dynamic_cast、reinterpret_cast、和const_cast..
关于强制类型转换的问题，很多书都讨论过，写的最详细的是C++ 之父的《C++ 的设计和演化》。最好的解决方法就是不要使用C风格的强制类型转换，而是使用标准C++的类型转换符：static_cast, dynamic_cast。标准C++中有四个类型转换符：static_cast、dynamic_cast、reinterpret_cast、和const_cast。下面对它们一一进行介绍。   static_cast   用法：static_cast < type-id > ( expression )   说明：该运算符把expression转换为type-id类型，但没有运行时类型检查来保证转换的安全性。   来源：为什么需要static_cast强制转换？情况1：void指针->其他类型指针 情况2：改变通常的标准转换 情况3：避免出现可能多种转换的歧义  它主要有如下几种用法：
用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换（把子类的指针或引用转换成基类表示）是安全的；进行下行转换（把基类指针或引用转换成子类指针或引用）时，由于没有动态类型检查，所以是不安全的。用于基本数据类型之间的转换，如把int转换成char，把int转换成enum。这种转换的安全性也要开发人员来保证。把void指针转换成目标类型的指针(不安全!!)把任何类型的表达式转换成void类型。注意：static_cast不能转换掉expression的const、volitale、或者__unaligned属性。   dynamic_cast   用法：dynamic_cast < type-id > ( expression )   说明：该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *；如果type-id是类指针类型，那么expression也必须是一个指针，如果type-id是一个引用，那么expression也必须是一个引用。  来源：为什么需要dynamic_cast强制转换？ 简单的说，当无法使用virtual函数的时候 典型案例： Wicrosoft公司提供给我们一个类库，其中提供一个类Employee.以头文件Eemployee.h和类库.lib分发给用户 显然我们并无法得到类的实现的源代码 //Emplyee.h class Employee  { public:     virtual int salary(); }; class Manager : public Employee { public:      int salary(); }; class Programmer : public Employee { public:     int salary(); };  我们公司在开发的时候建立有如下类: class MyCompany { public:     void payroll(Employee *pe);     //   }; void MyCompany::payroll(Employee *pe) {     //do something }  但是开发到后期，我们希望能增加一个bonus()的成员函数到W\$公司提供的类层次中。 假设我们知道源代码的情况下，很简单，增加虚函数： //Emplyee.h class Employee  { public:     virtual int salary();     virtual int bonus(); }; class Manager : public Employee { public:      int salary(); }; class Programmer : public Employee { public:     int salary();     int bonus(); }; //Emplyee.cpp   int Programmer::bonus() {     //   }  payroll()通过多态来调用bonus() class MyCompany { public:     void payroll(Employee *pe);     //   }; void MyCompany::payroll(Employee *pe) {     //do something     //pe->bonus(); }  但是现在情况是，我们并不能修改源代码，怎么办？dynamic_cast华丽登场了！ 在Employee.h中增加bonus()声明，在另一个地方定义此函数，修改调用函数payroll().重新编译，ok //Emplyee.h class Employee  { public:     virtual int salary(); }; class Manager : public Employee { public:      int salary(); }; class Programmer : public Employee { public:     int salary();     int bonus();//直接在这里扩展 }; //somewhere.cpp int Programmer::bonus() {     //define   }   class MyCompany { public:     void payroll(Employee *pe);     // }; void MyCompany::payroll(Employee *pe) {     Programmer *pm = dynamic_cast<Programmer *>(pe);          //如果pe实际指向一个Programmer对象,dynamic_cast成功，并且开始指向Programmer对象起始处     if(pm)     {         //call Programmer::bonus()     }     //如果pe不是实际指向Programmer对象，dynamic_cast失败，并且pm = 0     else     {         //use Employee member functions     } }  dynamic_cast主要用于类层次间的上行转换和下行转换，还可以用于类之间的交叉转换。 在类层次间进行上行转换时，dynamic_cast和static_cast的效果是一样的；在进行下行转换时，dynamic_cast具有类型检查的功能，比static_cast更安全。 class Base { public:     int m_iNum;     virtual void foo(); }; class Derived:public Base { public:     char *m_szName[100]; }; void func(Base *pb) {     Derived *pd1 = static_cast<Derived *>(pb);     Derived *pd2 = dynamic_cast<Derived *>(pb); }  在上面的代码段中， 如果pb实际指向一个Derived类型的对象，pd1和pd2是一样的，并且对这两个指针执行Derived类型的任何操作都是安全的； 如果pb实际指向的是一个Base类型的对象，那么pd1将是一个指向该对象的指针，对它进行Derived类型的操作将是不安全的（如访问m_szName），而pd2将是一个空指针(即0，因为dynamic_cast失败)。 另外要注意：Base要有虚函数，否则会编译出错；static_cast则没有这个限制。这是由于运行时类型检查需要运行时类型信息，而这个信息存储在类的虚函数表（关于虚函数表的概念，详细可见<Inside c++ object model>）中，只有定义了虚函数的类才有虚函数表，没有定义虚函数的类是没有虚函数表的。 另外，dynamic_cast还支持交叉转换（cross cast）。如下代码所示。 class Base { public:     int m_iNum;     virtual void f(){} }; class Derived1 : public Base { }; class Derived2 : public Base { }; void foo() {     derived1 *pd1 = new Drived1;     pd1->m_iNum = 100;     Derived2 *pd2 = static_cast<Derived2 *>(pd1); //compile error     Derived2 *pd2 = dynamic_cast<Derived2 *>(pd1); //pd2 is NULL     delete pd1; }  在函数foo中，使用static_cast进行转换是不被允许的，将在编译时出错；而使用 dynamic_cast的转换则是允许的，结果是空指针。   reinpreter_cast   用法：reinpreter_cast<type-id> (expression)   说明：type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数，也可以把一个整数转换成一个指针（先把一个指针转换成一个整数，在把该整数转换成原类型的指针，还可以得到原先的指针值）。   该运算符的用法比较多。   const_cast   用法：const_cast<type_id> (expression)   说明：该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外， type_id和expression的类型是一样的。  常量指针被转化成非常量指针，并且仍然指向原来的对象；常量引用被转换成非常量引用，并且仍然指向原来的对象；常量对象被转换成非常量对象。 Voiatile和const类试。举如下一例： class B{ public: int m_iNum; } void foo(){ const B b1; b1.m_iNum = 100; //comile error B b2 = const_cast<B>(b1); b2. m_iNum = 200; //fine }  上面的代码编译时会报错，因为b1是一个常量对象，不能对它进行改变；使用const_cast把它转换成一个常量对象，就可以对它的数据成员任意改变。注意：b1和b2是两个不同的对象。
展开全文
• static_cast和dynamic_cast是C++的类型转换操作符。编译器隐式执行的任何类型转换都可以由static_cast显式完成，即父类和子类之间也可以利用static_cast进行转换。而dynamic_cast只能用于类之间的转换。那么dynamic_...
• 本文简介C++中static_cast与dynamic_cast的使用场景，并介绍一些C++中的其他*caststatic_cast 你应该在牵涉到自定义的C++ class类型转换中用到它。因为它会帮你做一些静态类型检查。如下的例子是一种可能的应用...
目的
本文简介C++中static_cast与dynamic_cast的使用场景，并介绍一些C++中的其他*cast。
static_cast
你应该在牵涉到自定义的C++ class类型转换中用到它。因为它会帮你做一些静态类型检查。如下的例子是一种可能的应用场景：
#include <iostream>

class Me {
public: void print() {
std::cout << "Hello" << std::endl;
}
};

void printMe(void *me) {
Me *m = static_cast<Me *>(me);
m->print();
}

int main() {
Me me;
printMe(&me);
return 0;
}

如果上述的例子不太好体现static_cast做的静态类型检查，再看看下面的例子：
#include <iostream>

class Me {
public: void print() {
std::cout << "Hello" << std::endl;
}
};

class A : public Me {
};

class B {
};

int main() {
Me me;
A *a = static_cast<A *>(&me);
B *b = static_cast<B *>(&me); // ERROR
return 0;
}

上例会在将class Me 转换成class B时提示编译错误，因为编译器帮忙做了静态类型检查，发现class Me和class B没啥关系，不能直接转换。上例将class Me转换成class A虽然没有出现编译错误，但却是不合法的语句。因为基类不应该被转换成子类。
dynamic_cast
与static_cast相比，dynamic_cast可以提供运行时的动态类型检查，前提是需要打开编译器的rtti支持。因为dynamic_cast在运行时遇到不合理的向下类型转换时会返回空指针（上例中将class Me转换成class A）。 考虑如下的应用场景，checkMe()函数中接受包含Me指针的数组，但期望依据Me的子类类型做不同的事情：
class Me {
public: virtual ~Me() { }
public: void print() {
std::cout << "Hello" << std::endl;
}
};

class A : public Me { };
class B : public Me { };

void checkMe(const std::vector<Me *> &mes) {
for (auto &i : mes) {
A *a = dynamic_cast<A *>(i);
if (nullptr != a)
; // do someting
else
; // do something else
}
}

其他cast
const_cast
如程序中有过分使用的const限定修饰符，可以使用const_cast强制修改变量的值，如下例所示：
void calc(const int &v) {
int &tmp = const_cast<int &>(v);
tmp = 3;
}

reintepret_cast
reinteprete_cast和c的强制指针类型转换类似，转就完了，不做检查。一般用在将二进制数据流转换成结构体时。如下例所示，如果将下例的reinteprete_cast替换成static_cast会编译报错。
struct Byte {
int version;
};

void printByte(uint8_t *p) {
Byte *b = reinterpret_cast<Byte *>(p);
std::cout << b->version << " " << b->header << std::endl;
}

C-style cast
如果是c++中的基本数据类型，就用这个吧，上面的*cast写起来有点长。
总结
C++提供的 *cast可以提供静态或动态的类型检查。自定义的 C++ class可以用*cast, C++的基本数据类型用c风格的类型转换就好。static_cast 转换的合法性由程序员保证。dynamic_cast 需要用到rtti，跑起来会稍微慢一点点点点点儿。用不用看项目，看个人。
引用
[1] https://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast [2] https://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used
展开全文
• 一、隐式类型转换 系统自动进行，不需要程序开发人员介入。 int m = 3 +45.6; //把小数部分截掉，也属于隐式类型转换的一种...(5)一般static_cast和reinterpret_cast就能够很好的取代c语言风格的类型转换
一、隐式类型转换
系统自动进行，不需要程序开发人员介入。
int m = 3 +45.6; //把小数部分截掉，也属于隐式类型转换的一种行为。
doublen = 3 +45.6;
二、显示类型转换（强制类型转换）
int k = 5 % 3.2; // 语法错
int k = 5 %(int)3.2; // OK,C语言风格的强制类型转换
int k = 5 % int(3.2); // 函数风格的强制类型转换(C语言风格的强制类型转换)
c++强制类型转换分为4中：我们现在写程序应该使用c++风格的强制类型转换。
这4种强制类型转换，分别用于不同的目的，每一个都有一个不同的名字。提供4中类的目的：提供更丰富的含义和功能，更好的类型检查机制，方便代码的熟悉和维护
a)static_cast
b)dynamic_cast
c)const_cast
d)reinterpret_cast
这四个强制类型转换都被称呼为“命名的强制类型转换”
通用形式
强制类型转换名<type>(express)
强制类型转换名是上边a,b,c,d四个名字之一
type：换换的目标类型
express：你要转换的值
2.1static_cast
static_cast:静态转换,大家就理解成“正常转换”，编译的时候就会进行类型转换的检查
代码中要保证转换的安全性和正确性，static_cast含义跟c语言中的强制类型转换这种差不多
c风格的强制类型转换，以及编译器能够进行的隐式类型转换，都可以用static_cast类显示完成
可用于：
a)相关类型转换，比如整形和实型之间的转换：
double f = 100.34f;
int i = (int)f; // c风格的
int i2 = static<int>(f) // c++风格的类型转换
b)子类转成父类类型（继承关系），也能用这个static_cast转
class A {};
class B : public A {};

B b
A a = static_cast<A>(b); // 把子类转成父类的对象
c)void*与其他类型指针之间的转换,void*:无类型指针：可以指向任意类型指针（万能指针）
int i = 10;
int *p = &i;
void *q = static_cast<void *>(p); // int *转成void *,或者 void* q = p;
int *db = static_cast<int *>(q); // 需要使用static_cast才可以将void* 转为 int *
不可用于：
a)一般不能用于指针类型之间的转换比如int*转double*，float*转double*等。
d.static_cast总结:
编译器隐式执行的任何类型转换都可以由static_cast完成  当一个较大的算术类型赋值给较小的类型时，可以用static_cast进行强制转换。  可以将void*指针转换为某一类型的指针  可以将基类指针转换为派生类指针
#include <iostream>
using namespace std;

class Base {
};

class Derived :public Base {
};

int main() {
Base* base = new Derived;
Derived* derive = static_cast<Derived*>(base);
//Derived* derive = dynamic_cast<Derived*>(base);    // 错误的，原因：因为Base没有虚函数
}
2.2dynamic_cast
主要应用运行时类型识别的检查。主要用来父类型和子类型之间转换（父类型指针指向子类型对象，然后用dynamic_cast把父指针类型往子指针类型转）
2.3const_cast
a)去除指针或者引用的const属性。该转换能够将const性质转换掉。
编译时进行类型检查
const int ai = 90;
int ai2 = const_cast<int>(ai); // ai不是指针也不是引用不能转
const int *pai = &ai;
int *pai2 = const_cast<int *>(pai); // 语法正确
*pai2 = 120; // 这种写值行为是属于一种未定义行为。大家不要这么干
cout << ai << endl;
cout << *pai <<　endl;

// c风格强制类型转换
const int ai = 90;
int *pai = (int*)&ai;
*pai = 120; // 未定义行为
cout << ai << endl;
cout << *pai << endl;

#include <iostream>

using namespace std;

void func(int& val) {
cout << "func: " << val << endl;
}

//const_cast 用来移除对象的常量性
//const_cast一般用来用于指针或者引用
//const_cast去除常量性，不是为了修改他指定的内容
//const_cast去除常量性，为了函数能接受实参

int main() {

const int val = 100;
//int n = const_cast<int>(val);
//const_cast一般用于指针或者引用

//int* p = &val;
int* p = const_cast<int*>(&val);
*p = 200;
cout << val << endl;  // val 还是 100, 改变临时对象值
cout << "addr p: " << p << endl;
cout << "addr val: " << &val << endl;

const int val2 = 200;
//int& refval2 = val2;
int& refval2 = const_cast<int&>(val2);
refval2 = 300;
cout << "val2: " << val2 << endl;  // 改变临时对象值
//func(val2);
func(const_cast<int&>(val2));
return 0;
}
b)const_cast总结
用来移除对象的常量性(cast away the constness)  const_cast一般用于指针或者引用  使用const_cast去除const限定的目的不是为了修改它的内容  使用const_cast去除const限定，通常是为了函数能够接受这个实际参数
2.4reinterpret_cast
reinterpret：重新解释。（将操作系统内容解释为另一种不同的类型【能把操作数的类型都转了】）
处理无关类型的转换。也就是两个转换类型之间没有什么关系。就等于可以乱转，自由转。
常用于如下两种转换：
a)将一个整型（地址）转换成指针，一种类型指针转换成另一种类型指针，按照转换后的内容重新解释内存中的内容；
b)也可以从一个指针类型转换成一个整型
int i = 10;
int *pi = &i;
int *p2 = reinterpret_cast<int *>(&i);
char *pc = reinterpret_cast<char *>(pi); // 任意指针类型之间的转换

int i = 10;
int *pi = &i;
void *pvoid = reinterpret_cast<void *>(&i);
int *pi2 = reinterpret_cast<int *>(pvoid);
被认为是危险的类型转换，随便转，怎么搞都行，编译器都不报错
int iv1 = 100;
long long lv1 = 8898899400; // 8 字节的 十六进制： 2 126A 6DC8
int*piv1 = (int*)iv1; // c语言风格
int *piv2 = reinterpret_cast<int*>(iv1);
piv2 = reinterpret_cast<int *>(lv1);  // 整型转指针
long long ne = reinterpret_cast<long long>(piv2); // 指针转整型
c.reinterpret_cast总结
通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。
三.总结
(1)强制类型转换，不建议使用。强制类型转换能够抑制编译器报错
(2)学习目的：认识这些类型转换符，方便大家阅读别人代码。
(3)资料说：reinterpret_cast危险。使用const_cast意味着设计缺陷。
(4)如果实在需要使用类型转换，不要再使用c语言风格的类型转换了，而用c++风格的类型转换
(5)一般static_cast和reinterpret_cast就能够很好的取代c语言风格的类型转换

展开全文
• static_cast dynamic_cast reinpreter_cast const_cast  首先回顾一下C++类型转换： C++类型转换分为：隐式类型转换和显式类型转换   第1部分. 隐式类型转换 又称为“标准转换”，包括以下几种情况： 1) ...
• #endif // FBC_MESSY_TEST_STATIC_CAST_HPP_ #include "static_cast.hpp" #include void CCTest::setNumber(int num) { number = num; } void CCTest::printNumber() const { std::cout ; //this 指针的...
• reinterpret_cast 可以认为是 static_cast 的一种补充，一些 static_cast 不能完成的转换，就可以用 reinterpret_cast 来完成，例如两个具体类型指针之间的转换、int 和指针之间的转换（有些编译器只允许 int 转...
• 以下是对static_cast,dynamic_cast,reinterpret_cast和const_cast之间的区别进行了详细的介绍，需要的朋友可以过来参考下
• const_cast,dynamic_cast,reinterpret_cast,static_cast四种转换的区别一，const_cast一，dynamic_cast一，reinterpret_cast一，static_cast C++是一种强类型语言，对类型的检查非常严格，我们可以使用C语言中的...
• dynamic_cast运算符，用于将基类的指针或引用安全地转换成派生类的指针或引用。 当我们将这两个运算符用于某种类型的指针或引用时，并且该类型含有虚函数，运算符将使用指针或引用所绑定对象的动态类型 三种使用形式...
• static_cast < 新类型 > ( 表达式 ) 返回新类型的值 解释 只有下列转换在不去除常量性和易变性的场合才能用 static_cast 执行。 （1）下面情况类似 新类型 Temp(表达式) 存在从表达式到新类型的隐式转换...
• static_cast一般用来将枚举类型转换成整型，或者整型转换成浮点型。也可以用来将指向父类的指针转换成指向子类的指针。做这些转换前，你必须确定要转换的数据确实是目标类型的数据，因为static_cast不做运行时的类型...
• 在C++标准中，提供了关于类型层次转换中的两个关键字static_cast和dynamic_cast。 一、static_cast关键字（编译时类型检查） 用法：static_cast &lt; type-id &gt; ( expression )，该运算符把expression...
• error: invalid static_cast from type ‘Base1*’ to type ‘Base2*’ 总结：对于多种继承，如果pD真的是指向Derived，使用static_cast和dynamic_cast都可以转化为Derived，但是如果要转化为Base1的兄弟类Base2，...
• static_cast和dynamic_cast详解 C++标准转换运算符static_cast
• 在标准C++中有四个类型转换符：static_cast、dynamic_cast、const_cast和reinterpret_cast；下面将对它们一一的进行总结。 static_cast static_cast的转换格式：static_cast <type-id> (expression) ...
• void static_cast_demo() { int i = 0x12345; char c = 'c'; int* pi = &i; char* pc = &c; c = static_cast(i); //pc = static_cast*>(pi);//Error:无法从“int *”转换为“char *”,不能用于基本类型指针...
• 在我们进行c++编程时候，有时候我们希望显示地将对象强制转换成另外一...　c++为我们提供了4中强制类型转换：static_cast、dynamic_cast、const_cast和reinterpret_cast。 　下面我们就来谈谈这4中强制类型转换的用法。

...