文章目录
C++类型转换详解
在 C++编程中,类型转换是一个重要的概念。它允许我们在不同类型的数据之间进行转换,以满足特定的编程需求。C++中的类型转换主要包括隐式类型转换和显式类型转换,同时还有四种命名的强制类型转换操作符。
一、C 语言中的类型转换
在 C 语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化。C 语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换。
1. 隐式类型转化
隐式类型转化是编译器在编译阶段自动进行的,关联比较强的。
那么那些支持隐式类型转换的?
首先是我们熟悉的整形之间的转换(int,char double,有符号,无符号······),整形和浮点数之间的转换,
int i = 1;
double d = i; // 隐式类型转换,将整数 i 转换为浮点数 d
2. 显式类型转化
显式类型转化需要用户自己处理。
那么显示类型转换都有哪些呢?
指针和整形之间的转换,指针之间的转换
int* p = &i;
int address = (int) p; // 显示的强制类型转换,将指针 p 转换为整数 address
然而,C 语言中的类型转换存在一些缺陷,转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。
二、为什么 C++需要四种类型转换
C 风格的转换格式简单,但有不少缺点:
- 隐式类型转化在某些情况下可能会出问题,比如数据精度丢失。
- 显式类型转换将所有情况混合在一起,代码不够清晰。
因此,C++提出了自己的类型转化风格,同时为了兼容 C 语言,C++中还可以使用 C 语言的转化风格。
三、C++强制类型转换
标准 C++引入了四种命名的强制类型转换操作符:static_cast
、reinterpret_cast
、const_cast
、dynamic_cast
。
虽说C语言的类型转换兼容也可以用,但是C++的目的就是让语法更加规范
1. static_cast
这个就是隐式类型转换,C++中进行了语法的规范化
static_cast
用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用 static_cast
,但它不能用于两个不相关的类型进行转换。
//对应隐式类型转换
double d = 12.34;
int a = static_cast<int>(d); // 将浮点数 d 转换为整数 a
2. reinterpret_cast
同样的,reinterpret英文重新解释的意思,对应的就是强制类型转换。
reinterpret_cast
操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型。
//对应强制类型转换
double d = 12.34;
int a = static_cast<int>(d);
// 这里使用 static_cast 会报错,应该使用 reinterpret_cast
int *p = reinterpret_cast<int*>(a); // 将整数 a 转换为指针 p
3. const_cast
强转中的一种,有风险的去掉const的属性(其实强转也可以,还是那句话C++的目的是为了规范)
const_cast
最常用的用途就是删除变量的 const
属性,方便赋值。
void Test() {
const int a = 2;
int* p = const_cast<int*>(&a);
*p = 3;
cout << a << endl;
}
4. dynamic_cast
dynamic_cast
用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)。
向上转型:子类对象指针/引用 -> 父类指针/引用(不需要转换,赋值兼容规则)。
向下转型:父类对象指针/引用 -> 子类指针/引用(用 dynamic_cast
转型是安全的)。
注意:
dynamic_cast
只能用于父类含有虚函数的类。dynamic_cast
会先检查是否能转换成功,能成功则转换,不能则返回 0。
class A {
public:
virtual void f() {}
};
class B : public A {};
void fun(A* pa) {
// dynamic_cast 会先检查是否能转换成功,能成功则转换,不能则返回
B* pb1 = static_cast<B*>(pa);
B* pb2 = dynamic_cast<B*>(pa);
cout << "pb1:" << pb1 << endl;
cout << "pb2:" << pb2 << endl;
}
int main() {
A a;
B b;
fun(&a);
fun(&b);
return 0;
}
需要注意的是,强制类型转换关闭或挂起了正常的类型检查,每次使用强制类型转换前,程序员应该仔细考虑是否还有其他不同的方法达到同一目的。如果非强制类型转换不可,则应限制强制转换值的作用域,以减少发生错误的机会。强烈建议避免使用强制类型转换。
四、RTTI(了解)
RTTI(Run - time Type identification)即运行时类型识别,C++通过以下方式来支持 RTTI:
typeid
运算符。dynamic_cast
运算符。decltype
。
五、常见面试题
- C++中的 4 种类型转化分别是:
static_cast
、reinterpret_cast
、const_cast
、dynamic_cast
。 - 4 种类型转化的应用场景:
static_cast
:用于非多态类型的转换,例如基本数据类型之间的转换。reinterpret_cast
:用于进行底层的位模式重新解释,通常用于指针和整数之间的转换,或者不同类型指针之间的转换,但这种转换需要谨慎使用,因为它可能会导致未定义的行为。const_cast
:主要用于删除变量的const
属性,以便进行赋值操作。dynamic_cast
:用于在继承关系中进行安全的向下转型,确保只有在实际对象类型与目标类型匹配时才进行转换。