【C++】告别“类型转换”踩坑,从基础到四种核心强制转换方式
各位大佬好,我是落羽!一个坚持不断学习进步的学生。
如果您觉得我的文章还不错,欢迎多多互三分享交流,一起学习进步!
也欢迎关注我的blog主页:落羽的落羽
文章目录
一、回顾C语言的类型转换
C语言的类型转换主要是隐式类型转换和强制类型转换:
- 隐式类型转换,是编译器在特定情况下自动进行的类型转换,通常发生在不同类型的表达式运算中。主要是整型之间、整型与浮点型之间、浮点型之间的转换。
int a =1;double b =2.234; a = b;- 强制类型转换:是我们通过显式语法手动指定的类型转换,主要是整型和指针、指针和指针之间的转换。
int a =1;char* p =(char*)a;int* p1 =(int*)malloc(sizeof(int));但是,并非所有类型直接都能转换。例如double就无法转为指针类型。

二、C++中的类型转换
1. 内置类型转为自定义类型
随着自定义类型的广泛使用,C++也支持了内置类型和自定义类型之间的相互转换:
- 内置类型转换为自定义类型,需要自定义类型的相关构造函数支持。非常好理解,用内置类型转换为自定义对象,就相当于构造一个自定义对象。
classA{public:A(int a):a1(a),a2(a){}private:int a1;int a2;};
而当构造函数前加上关键字explicit,可以使这个构造函数不支持隐式类型转换。这就是之前我们学习智能指针时构造函数加了它的原因,我们不希望一个普通指针悄悄转换为智能指针。不过,还是支持强制类型转换的:

2. 自定义类型转为内置类型
一个自定义类型对象想要转换为内置类型,需要内部重载operator()。这里不是常规的运算符重载,和仿函数中重载operator()的写法也不一样。它的用法是operator 类型(){...}(也可以加explicit修饰),转换的方式是函数体内自定义的,举个例子:
classA{public:A(int a):a1(a),a2(a){}operatorint(){return a1 + a2;}private:int a1;int a2;};
智能指针中,关于向bool类型的转换,就是这样写的:

3. 自定义类型之间的转换
自定义类型之间的转换,也是需要有相关的构造函数,很好理解,不再赘述。
4. 类型安全与C++的四种强制类型转换方式
4.1 什么是类型安全?
类型安全是指,编程语言在编译和运行时提供保护机制,避免非法的类型转换和操作,导致出现内存访问错误等,从而减少程序运行时的错误。
C语言不是类型安全的语言, 因为C语言允许隐式类型转换,一些特殊情况下就会导致越界访问的内存错误。不合理的使用强制类型转换也会导致问题,比如一个int*的指针强转成 double*的话,访问就会出现越界。
C++兼容C语言,也支持隐式类型转换和强制类型转换,它也不是类型安全的语言。因此,C++提出了四个显示强制类型转换 操作符static_cast / reinterpret_cast / const_cast / dynamic_cast,就是为了让类型转换相对而言更安全。
4.2 static_cast
static_cast用于两个意义相近的类型之间的转换,比如整型之间、整型和浮点型之间、普通类型和其引用类型之间等。
double a =1.234;int b =static_cast<int>(a);float c =static_cast<float>(b);int&& d =static_cast<int&&>(b);4.3 reinterpret_cast
reinterpret_cast用于底层的类型转换,比如将一种类型的指针/引用直接转换为另一种类型。这种类型的转换后,对于内存的访问方式就会改变了,因此使用时需要很谨慎,自己要清楚明白使用后是否会出现问题。
int a =1;int* p1 =&a;char* p2 =reinterpret_cast<char*>(p1);4.4 const_cast
const_cast用于const对象向非const对象的转换,会去掉const属性,使用时同样需要谨慎。

4.5 dynamic_cast
dynamic_cast主要用于多态类型之间的转换,尤其是用于基类指针/引用向派生类指针/引用的转换,因为派生类的指针/引用向基类指针/引用的转换是天然支持的(也就是切片)。
但是,它不是简单基类转换为派生类。一个基类的指针/引用,它可能指向的是一个基类的对象,也可能指向的是一个派生类对象的切片。而dynamic_cast只能作用在后者,只有这个基类指针/引用指向的是派生类对象的切片,才能完成转换。对于前者情况,就不能转换,如果是基类指针指向基类,转换失败返回nullptr,如果是基类引用指向基类,转换失败抛出bad_cast异常。
dynamic_cast还要求基类必须是多态类型,也就是必须有虚函数,因为它的运行时通过虚表中存储的type_info来判断一个基类指针/引用指向的是基类对象还是派生类对象。
classA{public:virtualvoidfunc(){}};classB:publicA{};
本篇完,感谢阅读