【C++】强制类型转换 落日映苍穹つ 2022-05-18 02:24 256阅读 0赞 C++中四种强制类型转换:`static_cast, reinterpret_cast, const_cast, dynamic_cast` ##### 1. static\_cast(编译时类型检查) ##### 用于非多态类型之间的转换(静态转换),任何标准类型之间都可以用它,但它不能用于不相关类型之间的转换。主要有以下几种用法: 1. 用于基本的数据类型之间的转换,例如把int转换为char,把int转换为enum,但这种转换的安全性需要开发者自己保证,static\_cast所做的只是简单的截断; 2. 空指针转换成目标类型的空指针; 3. 任何类型的表达式转换成void类型; 4. 用于层次结构中父类和子类之间指针和引用的转换; 对于第4点,存在两种形式的转换,上行转换(子类到父类),下行转换(父类到子类);对于static\_cast,从子类到父类的转换是安全的,因为子类包含了父类的所有数据成员和函数成员,从子类转换到父类的指针对象可以没有任何顾虑的访问其成员;而对于从父类到子类的转换,因为static\_cast是在编译时进行类型检测,没有运行时的类型检查,是不安全的。 void Test() { double i = 2; int d = static_cast<int>(i); printf("%lf, %d\n", i, d); } ##### 2. dynamic\_cast(运行时类型检查) ##### 主要用于类层次结构中父类和子类之间指针和引用的转换,由于具有运行时类型检查,可以保证下行转换(父类到子类)的安全性,即:转换成功就返回转换后的正确类型指针,如果失败,返回NULL;而static\_cast如果失败,不会返回NULL,所以不安全。 总结为以下两句: * 对于上行转换,从子类到父类的转换,子类的指针指向的是子类对象,一般不会指向父类对象,所以static\_cast和dynamic\_cast效果一样; * 对于下行转换,从父类到子类的转换,如果父类的指针指向的是父类对象,那么static\_cast就会不安全,而dynamic\_cast在运行时检查过程中,判定不能转换,返回NULL;如果父类的指针指向子类对象,那么两个也都能成功。 class Base { virtual void fun() {} }; class Derived :public Base { }; void Test() { Derived* pb = new Derived; // 子类转父类 Base* pb1 = static_cast<Base*>(pb); Base* pb2 = dynamic_cast<Base*>(pb); Base *p1 = new Derived; // 父类转子类,父类指针指向子类对象 Derived *pd1 = static_cast<Derived *>(p1); Derived *pd2 = dynamic_cast<Derived *>(p1); Base *p2 = new Base; // 父类转子类,父类指针指向父类对象 Derived *pd3 = static_cast<Derived *>(p2); // 不安全 Derived *pd4 = dynamic_cast<Derived *>(p2); //pd4 = NULL; } ##### 3. reinterpret\_cast ##### 用于将一种类型转换为另一种不同的类型。用于底层的强制类型转换,导致实现依赖的结果(不可移植),例如:将一个指针转换为整数。 typedef void(*FUNC)(); int DoSomething(int i) { cout << "DoSomething" << endl; return 0; } void Test() { FUNC f = reinterpret_cast<FUNC>(DoSomething); f(); int i = 0; int p = reinterpret_cast<int>(&i);//将指针转换为整数 } ##### 4. reinterpret\_cast ##### 删除变量的const属性,方便赋值。 void test() { const int a = 5; int* pa = const_cast<int *>(&a); *pa = 10; cout << a << endl; //打印的结果还是5,由内存窗口可以看到值已经被改,因为编译器优化,到寄存器中取值 cout << *pa << endl; //结果是10,pa指向内存中的a,改的是内存中的值 } void test() { volatile const int a = 5; int* pa = const_cast<int *>(&a); *pa = 10; cout << a << endl; //打印的结是10,被volatile修饰,从内存中读取数据,解锁是10 cout << *pa << endl; }
还没有评论,来说两句吧...