一般常用的是C语言风格的强制类型转换(type) expression
,这种转换虽然简便,但很是粗糙,无法区分各种细致的转换(比如父类与基类之间的转换,const和非const之间的转换等),并且可能会带来一些难以察觉的问题。
C++为此推出了四种强制类型转换(static_cast
、const_cast
、dynamic_cast
、reinterpret_cast
),但很少有人会使用它们,甚至对此知之甚少。
1. static_cast
与C语言的强制类型转换风格类似,有着相似的含义和功能,一般我们用C语言强制类型转换时都是用此含义,所以以后需要用C语言风格的强制类型转换时可以用static_cast
来做,也更能表达清楚代码作用,当然其也有着与C语言风格强制类型转换相同的限制。
写法:static_cast<type>(expression)
注意事项:
- 其限制于基本类型间的数据类型转换
- 不能去除const属性或volatile属性,
const_cast
可以 - 不能直接进行普通变量、指针与引用之间的转换
- 其换类型检查非常严格,不同类型的指针不能直接转换,除非使用
void*
作为中间参数 - 其可以进行类继承体系中向上转换,但最好不要用,用
dynamic_cast
更好,其不能用于向下转换 - 有些时候隐式转换(也是一种C语言风格的强制转换)能够成功,但能用
static_cast
就要学着用它
示例:
void main() {
char char1 = 'a';
float float1 = char1; // 隐式转换成功,但不建议用
float float2 = static_cast<float>(char1); // 成功
double double1 = 0.01;
float float3 = static_cast<float>(double1); // 成功
int intPtr = 1;
float* floatPtr1 = &intPtr; // int*与float*之间隐式转换失败
float* floatPtr2 = static_cast<float*>(&intPtr); // 失败
void* voidPtr = &intPtr; // 任何指针都可以隐式转换为void*
void* voidPtr1 =static_cast<void*>(&intPtr); // 成功
float* float_ptr3 = voidPtr; // void*与float*之间隐式转换失败
float* float_ptr4 = static_cast<float*>(voidPtr); //成功
}
2. const_cast
专门用于去除const属性或volatile属性。
写法:const_cast<type>(expression)
注意事项:
- 其作用于同类型变量之间,只能有const或volatile的区别,不支持不同类型指针或引用之间的转换,比如说float转换成int是不允许的,转换前后的类型必须相同
示例:
/// 改变函数对变量操作规则
void function(const int& a){
int& b = const_cast<int&> a; // 同为int&,是同类型
b = a + 10;
}
void main(){
int c = 5;
function(c);
std::cout << c; // c的值变为了15
}
3. dynamic_cast
用于继承体系中类的转换,一般更多用于做向下或横向的安全转换,即把指向父类的指针转换为指向子类或父类的兄弟类的指针(或引用),但需要满足一定条件,见注意事项4。
写法:dynamic_cast<type>(expression)
注意事项:
-
其是在运行时处理的。(其他三种类型转换都是在编译时完成的)
-
其只能对指针或引用进行强制转换
-
其可以任意进行向上转换,即把指向子类的指针转换为父类的指针(或引用)
-
其对于转换的类具有多态性时,可以进行向下或横向转换,即把指向父类的指针转换为指向子类或父类的兄弟类的指针(或引用)
让类具有多态性即需要类有虚函数或者续继承的类
-
转换失败会返回空指针
示例:
class A {...}
class B {
virtual void test() {...}
...
}
class C : public A {...} // C为A的子类,不具有多态性
class D : public B { // D为B的子类,具有多态性
virtual void test() {...}
...
}
void main(){
/// 1
C* c;
A* a = dynamic_cast<A*>(c); // 成功,向上转换无特殊要求
/// 2
A* a;
C* c = dynamic_cast<C*>(a); // 失败,向下转换需要转换类C具有多态性
/// 3
B* b;
D* d = dynamic_cast<D*>(B); // 成功,类D具有多态性,可以向下转换
}
4. reinterpret_cast
用于将一种对象类型转换为另一种,不管它们是否相关,所以说它是C++中最接近于C风格强制类型转换的一个关键字。但一般用于在函数指针之间进行类型转换。
写法:reinterpret_cast<type>(expression)
注意事项:
- 其可以进行任意变量类型转换,包括普通变量、指针与引用之间,比如:float与double*之间
- 其转换结果常常是由编译器的实现所定义的,所以要注意不同编译器可能会造成不同转换结果,也就导致了其代码移植的局限性(所以很少有人经常使用这个类型转换)。