设为首页 收藏本站
查看: 6|回复: 0

[经验分享] 听说了吗,C++引入了四种强制类型转换

[复制链接]
累计签到:53 天
连续签到:2 天
发表于 2025-5-26 10:34:17 | 显示全部楼层 |阅读模式
转载自:CSDN _小羊_
一、类型转换
1、C语言中的类型转换
如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与
接收返回值类型不一致时,就需要发生类型转化,转换的前提是类型之间有一定的关联。

隐式类型转换:编译器自动进行,比如整形家族(int、char、unsigned int)/ 整型和浮点数
强制类型转换:我们自己处理,比如整形和指针、指针之间
[C++] 纯文本查看 复制代码
int main()

{

	int i = 1;

	// 隐式类型转换

	double d = i;



	int* p = &i;

	// 显示的强制类型转换

	int address = (int)p;



	return 0;

}


2、C++中的类型转换
上面举的例子都是内置类型之间,而内置类型和自定义类型之间、自定义类型和自定义类型之间都是可以通过一定的方式互相转换的。

| 内置类型和自定义类型之间:

在前面的学习中我们经常说:单参数构造函数支持隐式类型转换,多参数也可以通过加{}进行隐式类型转换。

[C++] 纯文本查看 复制代码
class A

{

public:

	A(int a)

		:_a1(a)

		,_a2(a)

	{}



	A(int a1, int a2)

		:_a1(a1)

		,_a2(a2)

	{}

private:

	int _a1;

	int _a2;

};



int main()

{

	string s("Are you ok?");//隐式类型转换

	A a1(1);//借助构造函数完成类型转换

	A a2({ 1, 2 });

	return 0;

}


C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数
构造函数前加explicit就不再支持隐式类型转换(但是还可以强转)
而自定义类型转换为内置类型需要通过下面这个函数:

[C++] 纯文本查看 复制代码
operator int()

{

	//...

}


这个函数没有返回类型,但是有返回值
函数前加explicit就不再支持隐式类型转换(但是还可以强转)
[C++] 纯文本查看 复制代码
class A

{

public:

	A(int a)

		:_a1(a)

		,_a2(a)

	{}



	A(int a1, int a2)

		:_a1(a1)

		,_a2(a2)

	{}



	operator int()

	{

		return _a1 + _a2;

	}

private:

	int _a1;

	int _a2;

};



int main()

{

	string s("Are you ok?");//隐式类型转换

	A a1(1);//借助构造函数完成类型转换

	A a2({ 1, 2 });



	int x = a1;

	int y = a2;

	cout << x << endl;

	cout << y << endl;

	return 0;

}


| 自定义类型和自定义类型之间:

自定义类型之间也可以借助构造函数来完成相互转换。

[C++] 纯文本查看 复制代码
class A

{

public:

	A(int a)

		:_a1(a)

		,_a2(a)

	{}



	A(int a1, int a2)

		:_a1(a1)

		,_a2(a2)

	{}



	operator int()

	{

		return _a1 + _a2;

	}



	int get() const

	{

		return _a1 + _a2;

	}

private:

	int _a1;

	int _a2;

};



class B

{

public:

	B(int b)

		:_b(b)

	{}



	B(const A& aa)

		:_b(aa.get())

	{}

private:

	int _b;

};



int main()

{

	A aa(1);

	B bb(2);

	bb = aa;//这里走了B的拷贝构造

	return 0;

}


例如:我们之前实现的list的迭代器有普通迭代器和const迭代器两种,普通迭代器用普通迭代器接收,const迭代器用const迭代器接收,而库中的list是支持普通迭代器用const迭代器接收的,那我们也可以给自己的list加上这个功能。

增加一个用于类型转换的构造函数:

[C++] 纯文本查看 复制代码
//...

ListIterator(const ListIterator<T, T&, T*>& it)

	:_node(it._node)

{}

//...


注意:这里的参数一定是写死的,不能是const ListIterator<T, Ref, Ptr>& it

3、C语言类型转换的缺陷
转换的可视性差,所有的转换形式都是以一种相同的形式书写,难以跟踪错误的转换
隐式类型转换有些情况下可能会出现问题,比如数据精度丢失
显示类型转换将所有情况混在一起,代码不够清晰

4、C++中的四种强制类型转换
标准C++为了加强类型转换的可视性,引入了下面四种命名的强制类型转换操作符。主要是为了让类型转换有统一的规范,更加严谨。

4.1 static_cast
static_cast用于非多态类型的转换(对应隐式类型转换),编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换。

[C] 纯文本查看 复制代码
int main()

{

	double d = 3.14;

	int a = static_cast<int>(d);

	cout << a << endl;

	return 0;

}



4.2 reinterpret_cast
reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型(对应强制类型转换)。

[C] 纯文本查看 复制代码
int main()

{

	double d = 3.14;

	int a = static_cast<int>(d);

	cout << a << endl;



	//这里使用static_cast会报错,应该使用reinterpret_cast

    //int *p = static_cast<int*>(a);

	int* p = reinterpret_cast<int*>(a);

	cout << p << endl;



	return 0;

}


4.3 const_cast
const_cast最常用的用途就是删除变量的const属性(对应强制类型转换中有风险的去掉const属性),方便赋值。

[C++] 纯文本查看 复制代码
int main()

{

	const int a = 2;

	int* p = const_cast<int*>(&a);

	*p = 3;

	cout << a << endl;

}


使用volatile可以确保编译器不会对这些变量的访问进行优化,从而确保每次访问都能读取到最新的值。


4.4 dynamic_cast
dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)。

向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)
向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)
注意:

dynamic_cast只能用于父类含有虚函数的类
dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回nullptr
[C++] 纯文本查看 复制代码
class A

{

public:

	virtual void f() {}

};

class B : public A

{};

void fun(A* pa)

{

	// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回

	B* pb1 = static_cast<B*>(pa);

	B* pb2 = dynamic_cast<B*>(pa);

	cout << "pb1:" << pb1 << endl;

	cout << "pb2:" << pb2 << endl;

}



int main()

{

	A a;

	B b;

	fun(&a);

	fun(&b);

	return 0;

}


dynamic_cast 作用于普通指针或引用,用于将基类指针(或引用)转换为派生类指针(或引用) 。

另外还有 dynamic_pointer_cast,专门用于智能指针的类型转换 ,将一个基类智能指针转换为派生类智能指针 。

二者都在运行时进行类型检查以确保转换安全性。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-1005723-1-1.html 上篇帖子: C++ 用实力碾碎所有否定,夺回本应属于它的地位 下篇帖子: C++的多态
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表