Cast: static_cast, dynamic_cast, const_cast, reinterpret_cast

Clips have been self : https://www.cnblogs.com/chenyangchun/p/6795923.html

   

1. c cast and c ++ cast

 c language casts primarily used to convert between data types on the basis of the syntax is:

(type-ID) expression The // convert the format 1

ID-type (expression The) // convert the format 2

 

c ++ in addition to the use of c outside the language of the cast, but also four new cast: static_cast , dynamic_cast , const_cast , reinterpret_cast , used primarily for mandatory conversion between the class hierarchy, the syntax is:

static_cast<new_type>      (expression)
dynamic_cast<new_type>     (expression)
const_cast<new_type>       (expression)
reinterpret_cast<new_type> (expression)

Note: new_type destination data type, expression for the original data type of the variable or expression.

In the "Effective C ++" c cast language called legacy transformation , c ++ cast called new transformation .

2. static_castdynamic_castconst_castreinterpret_cast

  •  static_cast

static_cast equivalent conventional C language cast, to the operator expression is converted to new_type type, used to force implicit conversions, e.g. non-const objects into const objects, compile-time checking, a non-polymorphic conversion , can be converted to a pointer and the other, but there is no run-time type checking to ensure the safety of conversion . It mainly has the following several uses:

a pointer to a class hierarchy between the base class (parent class) and a derived class (subclass) or reference conversion.

Converting an uplink (derived class pointer or reference into a base class shown) are safe ; and

When downstream converter (pointer or reference to the base class to the derived class represented converted), because there is no dynamic type checking, it is unsafe to.

for switching between the basic data types, such as the int converted to char , the int converted enum . Security developers such conversion should be guaranteed.

convert null pointer into the target type null pointer.

to convert any type of expression into a void type.

Note: static_cast can not convert out expression of const, volatile, or __unaligned property.

   

The basic types of data conversion for example as follows:

char A = 'A' ;
int B = static_cast < char > (A); //
correct, the char -converted data into int Data

double * = C new new double ;
void * D = static_cast < void *> (C); //
correct, the double translation pointer to void pointer

int E = 10;
const int F = static_cast < const int > (E); //
correct, the int -converted data into const int Data

int const g = 20 is;
int * H = static_cast < int *> (& g); //
compile error, static_cast not cast away g of const properties

   

Upstream and downstream conversion classes:

IF (= dp * Derived static_cast <Derived *> (bp)) { // downconversion unsafe
  //
use dp directed Derived objects } the else {   // use bp directed Base Object }  


  

if (Base * bp = static_cast < Derived *> (dp)) {// upconverter is safe
  //
use bp directed Derived objects } the else {   // use dp directed Base Object }  


  

 

   

  • dynamic_cast

dynamic_cast<type*>(e)
dynamic_cast<type&>(e)
dynamic_cast<type&&>(e)

type must be a class type, in a first form, type must be a valid pointer, in the second form, must be a left-type value, in a third form, a type must be the right value. In all forms of the above, any type of e must meet one of the following three conditions: the type of e is a type of public target type derived class, the type of e is the base class, or consensus type e type of target is a target type of type. If a conversion destination is a pointer type statement and dynamic_cast fails, the result is zero. If the target is a reference type and the conversion fails, then dynamic_cast operator throws an exception std :: bad_cast (the exception is defined in the standard library header files typeinfo). e may be a null pointer, the result is the desired type of null pointer.

dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换(cross cast)。

在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;

在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。dynamic_cast是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。

(1)指针类型

举例,Base为包含至少一个虚函数的基类,Derived是Base的共有派生类,如果有一个指向Base的指针bp,我们可以在运行时将它转换成指向Derived的指针,代码如下:

if(Derived *dp = dynamic_cast<Derived *>(bp)){
//
使用dp指向的Derived对象
}
else{
//
使用bp指向的Base对象
}

值得注意的是,在上述代码中,if语句中定义了dp,这样做的好处是可以在一个操作中同时完成类型转换和条件检查两项任务。

(2)引用类型

因为不存在所谓空引用,所以引用类型的dynamic_cast转换与指针类型不同,在引用转换失败时,会抛出std::bad_cast异常,该异常定义在头文件typeinfo中。

void f(const Base &b){
try{
const Derived &d = dynamic_cast<const Base &>(b);
//
使用b引用的Derived对象
}
catch(std::bad_cast){
//
处理类型转换失败的情况
}
}

   

  • const_cast

const_cast,用于修改类型的constvolatile属性。 

该运算符用来修改类型的const(唯一有此能力的C++-style转型操作符)或volatile属性。除了const 或volatile修饰之外, new_type和expression的类型是一样的。

常量指针被转化成非常量的指针,并且仍然指向原来的对象;

常量引用被转换成非常量的引用,并且仍然指向原来的对象;

③const_cast一般用于修改底指针。如const char *p形式。

   

举例转换如下:

const int g = 20;
int *h = const_cast<int*>(&g);//
去掉const常量const属性

const int g = 20;
int &h = const_cast<int &>(g);//
去掉const引用const属性

const char *g = "hello";
char *h = const_cast<char *>(g);//
去掉const指针const属性

   

  • reinterpret_cast

new_type必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。

reinterpret_cast意图执行低级转型,实际动作(及结果)可能取决于编辑器,这也就表示它不可移植

举一个错误使用reintepret_cast例子,将整数类型转换成函数指针后,vc++在执行过程中会报"...中的 0xxxxxxxxx 处有未经处理的异常: 0xC0000005: Access violation"错误:

#include <iostream>
using namespace std;
int output(int p){
cout << p <<endl;
return 0;
}

typedef int (*test_func)(int );//
定义函数指针test_func
int main(){
int p = 10;
test_func fun1 = output;
fun1(p);//
正确
test_func fun2 = reinterpret_cast<test_func>(&p);
fun2(p);//...
处有未经处理的异常: 0xC0000005: Access violation
return 0;
}

IBMC++指南C++之父Bjarne StroustrupFAQ网页和MSDNVisual C++也都指出:错误的使用reinterpret_cast很容易导致程序的不安全,只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。

MSDN中也提到了,实际中可将reinterpret_cast应用到哈希函数中,如下(64位系统中需将unsigned int修改为unsigned long):

// expre_reinterpret_cast_Operator.cpp
// compile with: /EHsc
#include <iostream>

// Returns a hash code based on an address
unsigned short Hash( void *p ) {
unsigned int val = reinterpret_cast<unsigned int>( p );
return ( unsigned short )( val ^ (val >> 16));
}

using namespace std;
int main() {
int a[20];
for ( int i = 0; i < 20; i++ )
cout << Hash( a + i ) << endl;
}

   

另外,static_cast和reinterpret_cast的区别主要在于多重继承,比如

   

class A {
public:
int m_a;
};

class B {
public:
int m_b;
};

class C : public A, public B {};

那么对于以下代码:

 

C c;
printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));

   

 前两个的输出值是相同的,最后一个则会在原基础上偏移4个字节,这是因为static_cast计算了父子类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处),而reinterpret_cast却不会做这一层转换。

因此, 你需要谨慎使用 reinterpret_cast。

   

3. c++强制转换注意事项

  • 新式转换较旧式转换更受欢迎。原因有二,一是新式转型较易辨别,能简化"找出类型系统在哪个地方被破坏"的过程;二是各转型动作的目标愈窄化,编译器愈能诊断出错误的运用。
  • 尽量少使用转型操作,尤其是dynamic_cast,耗时较高,会导致性能的下降,尽量使用其他方法替代。

   

参考资料:

a):http://en.cppreference.com/w/cpp/language/static_cast

b):http://en.cppreference.com/w/cpp/language/dynamic_cast

c):http://en.cppreference.com/w/cpp/language/const_cast

d):http://en.cppreference.com/w/cpp/language/reinterpret_cast

e):Effective C++》条款27:尽量少做转型动作

f): 百度百科

g) C++ Primer

Guess you like

Origin www.cnblogs.com/audacious/p/12236936.html