
各位大佬好,我是落羽!一个坚持不断学习进步的学生。 如果您觉得我的文章还不错,欢迎多多互三分享交流,一起学习进步! 也欢迎关注我的blog主页: 落羽的落羽
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++也支持了内置类型和自定义类型之间的相互转换:
class A
{
public:
A(int a)
:a1(a)
,a2(a)
{ }
private:
int a1;
int a2;
};
而当构造函数前加上关键字explicit,可以使这个构造函数不支持隐式类型转换。这就是之前我们学习智能指针时构造函数加了它的原因,我们不希望一个普通指针悄悄转换为智能指针。不过,还是支持强制类型转换的:

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

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

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