C++:类型转换(static_cast、reinterpret_cast、const_cast、dynamic_cast)、RTTI
- 一、C语言类型转换
 - 二、C++新增强制类型转换
 - 2.1 新增类型转换:static_cast
 - 2.2 新增类型转换: reinterpret_cast
 - 2.3 新增类型转换:const_cast
 
- 2.4 新增类型转换:dynamic_cast
 - 三、 什么是RTTI ?
 
一、C语言类型转换
在C中支持类型转换, 分为隐式类型转换和显示类型转换。但C中类型转换不是非常规范不规范,存在以下问题:
- 隐式类型转换:编译器在编译阶段自动转换。如果不能转换,编译失败。
 - 显示类型转换:用户自己处理。
 
二、C++新增强制类型转换
由于C语言两种类型转换方式都存在缺陷:隐式类型转换会导致诸如数据精度丢失等问题;而显示类型转化代码不清晰。所以C++在兼容C的基础之上,增加了4中强制类型转换:static_cast、reinterpret_cast、const_cast、dynamic_cast。
2.1 新增类型转换:static_cast
 static_cast用于非多态的类型的转化,即静态转化。static_cast和C中的隐式类型转换类似,编译器会自动进行类型转换。如果不能转换,则编译失败!
int main()
{
	double d = 123.12l;
	int i = static_cast<int>(d);
	return 0;
}
 
2.2 新增类型转换: reinterpret_cast
 reinterpret_cast对标的是C中的显示类型转换。需要注意的是显示类型转换通常会伴随风险,使用reinterpret_cast不会进行类型安全检查。
int main()
{
	int i = 3;
	//int* p = static_cast<int*>(i); //error
	int* p = reinterpret_cast<int*>(i);
	return 0;
 
2.3 新增类型转换:const_cast
 const_cast用于去除变量的const属性,使变量能够进行赋值操作。
 【实例】:
int main()
{
	const int i = 2;
	int* p = const_cast<int*>(&i);//删除常变量i的const属性
	(*p)++;
	//cout << i << ":" << *p << endl;
	printf("i=%d, *p=%d\n", i, *p);
	return 0;
}
 

- 既然我们已经使用
const_cast删除了变量i的const属性,为什么这里i的结果认为2? - 原因在于编译器的优化。当一个变量为const属性时,编译器认为该变量不在被修改,所以会用一个寄存器直接保存该变量的结果;或者在编译阶段直接类似宏替换,将i替换为2。
 
所以我们可以通过关键字volatile禁止编译器对常变量的优化!!
int main()
{
	volatile const int i = 2;
	int* p = const_cast<int*>(&i);//删除常变量i的const属性
	(*p)++;
	//cout << i << ":" << *p << endl;
	printf("i=%d, *p=%d\n", i, *p);
	return 0;
}
 

- 这里输出时不要用cout。原因在于这里使用
volatile后,由于C++标准输出库存在缺陷,没有匹配到正确的重载函数。 
2.4 新增类型转换:dynamic_cast
 dynamic_cast用于动态转换,将一个父类对象的指针或引用转换为一个子类对象的指针或引用。
- 向上转换:子类对象指针/引用->父类指针/引用(我们认为该过程是天然的,不产生临时变量。通过赋值兼容规则(切片)直接将子类对象指针/引用给父类指针/引用)
 - 向下转换:父类指针/引用->子类对象指针/引用。这种情况下,如果直接强转类型,可能回到住越界访问的风险。而
dynamic_cast则可以避免该问题。(具体看实例) 
tips:
- dynamic_cast只能用于父类含有虚函数的类!!
 dynamic_cast会先检查能否转换成功。如果能成功,则进行转换。否则返回一个空指针!!
void func(A* pa)
{
	//不安全, 原因在于如果是一个A类型的指针转递给pa,此时后续访问_b是发生越界访问
	//B* ptr = (B*)pa;
	//使用dynamic_cast,如果将A类型的指针转递给pa会转换失败,返回空指针
	//而将B类型的指针转递给pa, 转换成功,恢复到原始状态
	B* ptr = dynamic_cast<B*>(pa);
	if (ptr)
	{
		ptr->_a++;
		ptr->_b++;
		cout << ptr->_a << ":" << ptr->_b << endl;
	}
	else
	{
		cout << "转换失败" << endl;
	}
}
int main()
{
	A a;
	B b;
	cout << "B b -> func(&a):" << endl;
	func(&a);//转换失败
	cout << endl;
	cout << "A a -> func(&b):" << endl;
	func(&b);
	return 0;
	return 0;
}
 

三、 什么是RTTI ?
RTTI:Run-time Type identification的简称,即:运行时类型识别。C++通过以下方式来支持RTTI:
- typeid运算符
 - dynamic_cast运算符
 - decltype
 




![[云服务器14] 搭建属于你自己的Git服务器](https://i-blog.csdnimg.cn/direct/e243ff53c10f40638811375f6960166e.png#pic_center)













