从C开始的CPP学习生活06-类型转换

1、旧式类型转换

1
2
(type)value;
type(value); //C++特有

2、新式类型转换

新式类型转换针对不同的场景使用不同的转换方式,相较于就是转换的有点是安全

  • static_cast
  • const_cast
  • dynamic_cast
  • reinterpret_cast

2.1、static_cast

static_cast明确告知编译器我们要进行类型转化,

可以使用static_cast进行转化的类型主要有三种

  • 浮点型转换成整型
  • 枚举型转换成整型
  • 父类转换成子类
1
2
3
4
double a = 1.1;
int b = static_cast<int>(a);
//这里可以直接写
int b = a;//但是这种写法编译器会报出warning,使用static_cast就是告知编译器我知道可能会出现精度缺失,你不用担心
1
2
3
4
5
6
enum class Color {red = 0, blue};

int main()
{
int r = static_cast<int>(Color::blue);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class CFather {};

class CSon : public CFather
{
public:
int b;
};

int main()
{
CFather* p = new CFather;
CSon* s = static_cast<CSon*>(p);
return 0;
}

虽然使用static_cast将父类指针转换成子类指针是可以实现的,但是这种方法并不安全,如我们可以访问s->b;但实际的情况是s->b是一块不属于该指针的内存,这属于非法访问,所以不推荐使用这种类型转换,而是推荐使用dynamic_cast

2.1.1、static_cast不能转换两个没有关系的类

1
2
3
class C {};

C* c = static_cast<C*>(p);//ERROR

2.1.2、static_cast不能将const类型的值转换成非const类型的,但是C风格的旧式转换可以

1
2
3
const int* a = new int(1);
int *r = static_cast<int*>(a);//ERROR
int *r = (int*)a;

2.2、dynamic_cast

dynamic_cast多用于有继承关系的多态类(基类里面含有虚函数)的指针或引用之间的转换。

dynamic_cast运算符能够将基类的指针或引用安全的转换为派生类的指针或者引用。转换失败,返回空地址。

RTTI(Runtime Type Identification),程序在运行阶段确定对象的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct A
{
virtual ~A() {}
};

struct B : A {};
struct C {};

int main()
{
A* a = new B;
B* b = dynamic_cast<B*>(a);
delete a;
return 0;
}

上述的转换是安全的

1
2
A* a = new A;
B* b = dynamic_cast<B*>(a);//b -> null

这种转换dynamic_cast并不支持,因为仍有可能访问到非法内存,所以会返回一个null

2.3、const_cast

const_cast主要用来去除符合类型中的const和volatile属性

由于变量本身的const属性是不能去除的,要想修改变量的值,只能先去除变量的const属性,然后再进行修改

const_cast就是负责将对象的类型由const type变为type

注意:源类型和目标类型除了const不同外,其他地方完全相同

2.4、reinterpret_cast

reinterpret_cast用于各种类型的转换,即reinterpret_cast允许将任意指针转换到其他指针类型,也允许做任意整数类型和任意指针类型之间的转换。

reinterpret_cast转换是不安全的,程序的安全性需要程序员自己来保证。


从C开始的CPP学习生活06-类型转换
http://example.com/2022/10/26/cppnote06/
作者
Anhongzhan
发布于
2022年10月26日
许可协议