【C++练级之路】【Lv.26】类型转换
创始人
2024-12-27 19:04:58
0



快乐的流畅:个人主页


个人专栏:《算法神殿》《数据结构世界》《进击的C++》

远方有一堆篝火,在为久候之人燃烧!

文章目录

  • 一、C风格类型转换
    • 1.1 隐式类型转换
    • 1.2 显式类型转换
  • 二、C++风格类型转换
    • 2.1 static_cast
    • 2.2 dynamic_cast
    • 2.3 const_cast
    • 2.4 reinterpret_cast
  • 三、RTTI
    • 3.1 typeid
    • 3.2 dynamic_cast
    • 3.3 decltype
  • 总结

一、C风格类型转换

1.1 隐式类型转换

隐式类型转换(Implicit Type Conversion),又称自动类型转换,由编译器在编译阶段自动进行,能转就转,不能转就编译失败。

常见的隐式类型转换包括:

  • 赋值运算符中的类型转换:例如从 int 赋值转换为 double
  • 算术运算符中的类型转换: 例如 intlong 进行运算,会被提升为 long 。同时,超出类型的表示范围,会进行符号扩展或截断。
  • 函数调用中的类型转换:实参与形参类型不匹配,会尝试转换为与形参匹配的类型。
  • 布尔值中的类型转换:对于数值类型,非零值转换为 true ,零值转换为 false ;对于指针类型,非空指针转换为 true ,空指针转换为 false
  • 指针中的类型转换:指针可以隐式转换为 void* 类型。数组名会被转换为指向数组第一个元素的指针,函数名会被转换为指向该函数的指针。
void func(double d){}  void test() { 	int i = 1; 	double d = i;//赋值运算符 	double ret = i + d;//算术运算符 	func(i);//函数调用 	void* p = &i;//指针 } 

1.2 显式类型转换

显式类型转换(Explicit Type Conversion),又称为强制类型转换,需要程序员显式地指定转换方式。

格式:(type)expression

void test() { 	int i = 1; 	double d = (double)i; } 

二、C++风格类型转换

2.1 static_cast

格式:static_cast(expression)

用于非多态类型的转换(静态转换),并且只适用相近类型之间的转换,对应C的隐式类型转换,例如基本数据类型之间的转换。

void test() { 	int i = 1; 	double d = static_cast(i);//静态转换,相近类型 	int* pi = &i; 	void* p = static_cast(pi); } 

2.2 dynamic_cast

格式:dynamic_cast(expression)

用于多态类型的转换(动态转换),并且用于向下转型:将一个父类对象的指针/引用转换为子类对象的指针或引用。

ps:向上转型,没有类型转换,属于赋值兼容规则。

class A { public: 	virtual void f(){}  	int _a = 1; };  class B :public A { public: 	virtual void f(){}  	int _b = 2; };  void test() { 	B b; 	A a = b; 	A& ra = b;//此处没有隐式类型转换  	double d = 3.14; 	const int& ri = d;//此处有隐式类型转换 } 

由于类型转换后的临时对象具有常性,所以要用常引用。而向上转型(切片)不用常引用,所以没有发生类型转换。


dynamic_cast 在运行时检查转换是否有效。如果转换无效,则指针类型返回空指针 nullptr,引用类型抛出异常 std::bad_cast

void func(A* pa) { 	//B* p = (B*)pa;//直接向下转换,如果指向父类,则存在越界风险 	B* p = dynamic_cast(pa); 	if (p) 	{ 		p->_a++; 		p->_b++; 	} 	else 	{ 		cout << "转换失败" << endl; 	} }  void test() { 	B b; 	A a = b; 	func(&a); 	func(&b); } 

直接向下转换,如果指向父类,则存在越界风险。运用 dynamic_cast 则可安全地进行向下转型。

2.3 const_cast

格式:const_cast(expression)

用于修改对象的常量属性,可添加或移除变量的 constvolatile 属性。

void test() { 	const int a = 2; 	int* p = const_cast(&a); 	*p = 3; 	 	cout << a << endl; 	cout << *p << endl;  	cout << &a << endl; 	cout << p << endl; } 

通过打印可以发现,a的值依旧为2,而*p的值为3,并且它们的地址相同。这是为什么呢?其实,编译器在这里做了优化,常变量a会被放进寄存器或者直接替换

这时我们可以加上 volatile 关键字,其作用是阻止编译器对标记的变量进行某些优化。

void test() { 	volatile const int a = 2; 	int* p = const_cast(&a); 	*p = 3; 	 	cout << a << endl; 	cout << *p << endl;  	//cout << &a << endl; 	printf("%p\n", &a); 	cout << p << endl; } 

此时还有一个问题,那就是用 volatile 修饰的变量类型无法和参数为 void*operator<< 函数匹配,从而会匹配到不合适的重载函数,输出错误的地址值。所以,此处我们用 printf 进行打印即可。

2.4 reinterpret_cast

格式:reinterpret_cast(expression)

为操作数的位模式提供较低层次的重新解释。用于不相近类型之间的转换,对应C的显式类型转换。

void test() { 	int i = 1; 	int* p = &i; 	//double* p1 = static_cast(i);//error 	double* p2 = reinterpret_cast(i); 	//double* p3 = static_cast(p);//error 	double* p4 = reinterpret_cast(p); } 

三、RTTI

RTTI(Run-Time Type Identification)是C++语言中的一个特性,它允许程序在运行时确定对象的实际类型

3.1 typeid

用于打印变量的类型。

void test() { 	auto f = [](int x, int y){return x + y;}; 	cout << typeid(f).name() << endl; } 

3.2 dynamic_cast

class Base {}; class Derive :public Base {};  void func(Base* pb) { 	Derive* pd = dynamic_cast(pb); } 

3.3 decltype

可将变量的类型提取,作为参数传递。

void test() { 	int x = 1; 	double y = 2.0;  	auto ret = x * y; 	vector v; } 

总结

C风格的类型转换,将不同类型的转换混在一起,不够清晰,可视性差,难以跟踪错误的转换。所以我们推荐使用C++的类型转换,加强类型转换的可视性,提高代码的可读性与可维护性。


一般来说:

  • 使用 static_cast 进行相近类型的转换。
  • 使用 dynamic_cast 在运行时进行多态类型检查。
  • 使用 const_cast 移除或添加常量性。
  • 使用 reinterpret_cast 进行不相近类型的转换。

真诚点赞,手有余香

相关内容

热门资讯

重大通报,牛牛房卡游戏平台加盟... 九酷大厅/随意玩房卡更多详情添加微:33549083、 2、在商城页面中选择房卡选项。 ...
秒懂教程,炸金花房卡专卖店联系... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
玩家攻略,金花微信链接市场价格... 玩家攻略,金花微信链接市场价格表新西游/飞鹰互娱/微信链接房卡销售购买新西游/飞鹰互娱是一款非常受欢...
ia攻略/斗牛房间怎么创建的钻... 钻石大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:【3329006910】或QQ:332900...
终于懂得,金花房卡微信链接怎么... 新七喜是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:15984933许多玩家在游戏中会购买房卡来享...
一分钟了解!微信金花房卡怎么弄... 您好!微信九哥联盟大厅链接获取房卡可以通过以下几种方式购买: 1.微信渠道:(九哥联盟)大厅介绍:...
ia攻略/牛牛房卡批发平台战神... 今 日消息,战神联盟房卡添加微信33549083 苹果今日发布了 iOS 16.1 正式版更新,简单...
玩家必备攻略,微信群牛牛房卡去... 牛牛大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来...
重大通报,牛牛充值房卡新海贝/... 微信游戏中心:新海贝/青鸟大厅房卡在哪里买打开微信,添加客服微信【88355042】,进入游戏中心或...
一分钟普及,购买金花房卡联系方... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡...
正规平台有哪些,金花微信链接市... 今 日消息,新八戒房卡添加微信33549083 苹果今日发布了 iOS 16.1 正式版更新,简单介...
带你快速了解,金花房卡购买流程... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
ia攻略/金花房卡制作链接桃花... 桃花大厅房卡更多详情添加微:33549083、 2、在商城页面中选择房卡选项。 3、根...
正规平台有哪些,牛牛房卡批发平... 微信游戏中心:长虹大厅房卡在哪里买打开微信,添加客服微信【88355042】,进入游戏中心或相关小程...
秒懂普及,牛牛链接房卡那里有冷... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
玩家攻略,游戏微信牛牛房卡芙蓉... 玩家攻略,游戏微信牛牛房卡芙蓉大厅/开群怎么买房卡Sa9Ix苹果iPhone 17手机即将进入量产阶...
头条推荐!牛牛房卡出售桃花大厅... 今 日消息,桃花大厅房卡添加微信33549083 苹果今日发布了 iOS 16.1 正式版更新,简单...
ia攻略/牛牛房卡出售玉兔大厅... 玉兔大厅房卡更多详情添加微:33549083、 2、在商城页面中选择房卡选项。 3、根...
科技实测!微信金花房卡怎么弄龙... 科技实测!微信金花房卡怎么弄龙王大厅/开群怎么买房卡龙王大厅是一款非常受欢迎的游戏,咨询房/卡添加微...
玩家必备攻略,微信炸金花房卡链... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:15984933许多玩家在游戏中会购买房卡...