C++ 类型转换(23)
2022-06-30 本文已影响0人
maskerII
一、前言
类型转换(cast)是将一种数据类型转换成另一种数据类型。例如,如果将一个整型值赋给一个浮点类型的变量,编译器会暗地里将其转换成浮点类型。
转换是非常有用的,但是它也会带来一些问题,比如在转换指针时,我们很可能将其转换成一个比它更大的类型,但这可能会破坏其他的数据。
应该小心类型转换,因为转换也就相当于对编译器说:忘记类型检查,把它看做其他的类型。
一般情况下,尽量少的去使用类型转换,除非用来解决非常特殊的问题。
标准c++提供了一个显示的转换的语法,来替代旧的C风格的类型转换。
使用C风格的强制转换可以把想要的任何东西转换成我们需要的类型。那为什么还需要一个新的C++类型的强制转换呢?
新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。C++风格的强制转换其他的好处是,它们能更清晰的表明它们要干什么。程序员只要扫一眼这样的代码,就能立即知道一个强制转换的目的。
二、静态转换 static_cast
2.1 基础类型 转换
// 1. 基础类型 转换
void test01()
{
char a = 'a';
// char->double
// static_cast<要转到的类型>(需要将谁转换)
double d = static_cast<double>(a);
double d1 = (double)a;
cout << d << " " << d1 << endl;
}
2.2 有层次关系类的指针或引用 转换
// 2.有层次关系类的指针或引用 转换
class Father
{
};
class Son:public Father
{
};
class Other
{
};
// 指针转换
void test02() {
Father *f = NULL;
Son *s = NULL;
// 向上转换 安全
Father *f1 = static_cast<Father*>(s);
// 向下转换 不安全
Son *s1 = static_cast<Son*>(f);
// 没有继承关系的类之间的指针不能转换 报错
// Other *other = static_cast<Other *>(f); Err
}
// 引用转换
void test03() {
Father f;
Son s;
Father &ref_f = f;
Son &ref_s = s;
// 向上转换 安全
static_cast<Father &>(ref_s);
// 向下转换 不安全
static_cast<Son &>(ref_f);
}
三、动态转换 dynamic_cast
dynamic_cast 主要用于类层次间的上行转换和下行转换
在类层次间上线转换时,dynamic_cast和static_cast的效果是一样的,但在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全
// 动态转换 dynamic_cast
void test04() {
// char a = 'a';
// dynamic_cast<double>(a); 基础类型不能使用动态转换dynamic_cast
Father *f = NULL;
Son *s = NULL;
// 向上转换,安全
Father *f1 = dynamic_cast<Father *>(s);
// 向下转换,不安全,会去检查 报错
// Son *s1 = dynamic_cast<Son *>(f);
}
// 发生多态,向下转换,动态转换不报错
class Father2
{
public:
virtual void func(){
}
};
class Son2: public Father2
{
public:
virtual void func(){
}
};
void test05() {
Father2 *f = new Son2;
// 向下转换
dynamic_cast<Son2 *>(f);
}
四、常量转换const_cast
常量指针被转化为非常量指针,并且仍然指向原来对象
常量引用被转化为非常量引用,并且仍然指向原来对象
注意:不能直接对非指针或非引用的变量进行const_cast操作符去直接移除它的const
// 常量转换const_cast
void test06() {
const int *p = NULL;
// const -> 不带const
int *newP = const_cast<int *>(p);
int *pp = NULL;
const int* newPP = const_cast<const int *>(pp);
int a = 10;
int &ref_a = a;
const int &ref_a1 = const_cast<const int &>(ref_a);
cout << ref_a1 << endl;
int b = 20;
const int &ref_b = b;
int& ref_b1 = const_cast<int &>(ref_b);
cout << ref_b1 << endl;
}
五、重新解释转换(reinterpret_cast)
重新解释转换(reinterpret_cast) 不安全
主要用于将一种数据类型从一种类型转换为另一种类型
它可以将一个指针转成一个整数,也可以将一个整数转成一个指针
// 重新解释转换(reinterpret_cast)
class Father
{
};
class Other
{
};
void test07() {
int a = 10;
int *p = reinterpret_cast<int *>(a);
cout << p << endl;
Father *f = NULL;
Other *o = reinterpret_cast<Other *>(f);
}