【C++】类型转换

这篇具有很好参考价值的文章主要介绍了【C++】类型转换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、C语言中的类型转换

在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化,C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换

  1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败
  2. 显式类型转化:需要用户自己处理

例如:

				void Test()
				{
					int i = 1;
					// 隐式类型转换
					double d = i;
					printf("%d, %.2f\n", i, d);
				
					int* p = &i;
					// 显示的强制类型转换
					int address = (int)p;
					printf("%x, %d\n", p, address);
				}

缺陷:转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。

二、C++强制类型转换

标准 C++ 为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:
static_cast、reinterpret_cast、const_cast、dynamic_cast

1. static_cast

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

例如,相近的类型可以用 static_cast,即意义相似的类型,如下:

				int main()
				{
					double d = 12.34;
					int a = static_cast<int>(d);
					cout << a << endl;
				
					return 0;
				}

但是有一定关联,意义不相似的类型不可以用 static_cast,例如:

				int* ptr = static_cast<int*>(a);

以上语句会发生报错;那么以上语句应该用什么呢?我们往下看。

2. reinterpret_cast

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

像上面这种意义不相似的类型我们应该使用 reinterpret_cast,例如:

				int main()
				{
					int a = 12;
					int* ptr = reinterpret_cast<int*>(a);
				
					return 0;
				}

3. const_cast

const_cast 最常用的用途就是删除变量的 const 属性,方便赋值。

例如:

				int main()
				{
					const int a = 2;
					int* p = const_cast<int*>(&a);
					*p = 3;
				
					return 0;
				}

但是这里有一个奇怪的现象,我们将 a 的值和 *p 的值打印出来,并且将它们的地址打印出来观察:

【C++】类型转换,C++,c++,jvm,开发语言

我们会发现,a 和 p 的地址是一样的,但是当我们修改 *p 的时候,a 的值为什么不变呢?

其实这里和编译器的优化有关系,const 修饰的变量,编译器通常会对它进行优化,它通常会认为 const 修饰的变量不会被修改,所以编译器不会每次都去内存去取数据,它会将数据放在寄存器,甚至用一个常量去替代,类似于宏一样,当我们需要打印数据时,就直接用初始数据替代我们的 const 变量;所以当我们内存中的数据被修改了,但是编译器没有去内存中去取数据,所以 a 的值没有受影响。

如果我们想让编译器每次都去内存中去取数据呢?我们可以使用关键字 volatile,我们在 const 变量前加上这个关键字,就是告诉编译器不需要对该 const 变量进行优化,每次都去内存中取数据,如下:

				int main()
				{
					volatile const int a = 2;
					int* p = const_cast<int*>(&a);
					*p = 3;
				
					cout << a << endl;
					cout << *p << endl;
				
					cout << &a << endl;
					cout << p << endl;
				
					return 0;
				}

【C++】类型转换,C++,c++,jvm,开发语言

我们可以看到 a 和 *p 的值就一样了。但是我们又发现了另外一个问题,为什么 &a 的值是 1 呢?这是因为 cout&a 识别的时候匹配错了,我们只需要将 &a 强转成如下即可:

【C++】类型转换,C++,c++,jvm,开发语言

如果以上的转换我们使用C语言的强制类型转换可以吗?我们可以尝试一下:

				int main()
				{
					const int a = 2;
					int* p = (int*)&a;
					*p = 3;
				
					cout << a << endl;
					cout << *p << endl;
				
					cout << &a << endl;
					cout << p << endl;
				
					return 0;
				}

【C++】类型转换,C++,c++,jvm,开发语言

如上图,也是可以完成转换的。那么C++为什么要使用这几种类型转换的方式呢?其实C++是为了增强程序的可读性,为了将它们区分开来,例如意义相类似的就用 static_cast;意义不相似的就用 reinterpret_castconst_cast 就说明这个类型转换不安全。

4. dynamic_cast

dynamic_cast 用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换),这个是C语言不具备的。

  • 向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)

怎么理解向上转换呢?假设有一个父类 A,一个子类 B,以下场景是不需要转换的,因为符合赋值兼容规则:

				int main()
				{
					B objb;
					A obja = objb;
					A& ra = objb;
				
					return 0;
				}

其中 A& ra = objb; ra 引用的是objb 中父类的部分,即发生了切割,ra 就是 objb 中父类的部分的别名。

  • 向下转型:父类对象指针/引用->子类指针/引用(用 dynamic_cast 转型是安全的)

向下转换的规则:父类对象不能转换成子类对象,但是父类指针和引用可以转换成子类指针和引用。

如果我们直接使用强制类型进行向下转换,是不安全的,例如以下场景:

有两个类,分别是父类和子类:

				class A
				{
				public:
					virtual void f(){}
					int _a = 1;
				};
				
				class B : public A
				{
				public:
					int _b = 2;
				};

当我们分别定义两个类的对象,传给 func 函数:

				void func(A* pa)
				{
					B* ptr = (B*)pa;
					ptr->_a++;
					ptr->_b++;
				}
				
				int main()
				{
					A a;
					B b;
					func(&a);
					func(&b);
				
					return 0;
				}

如果是 func(&b); 那么在 func 函数内就是将父类的对象重新转换为子类,是没有问题的,因为在传入前它本身就是子类的对象。

但是如果是 func(&a); 就会存在越界问题,因为在传入时是父类的对象,在 func 函数内部将该父类对象强制转换成子类对象,那么它本身是父类对象,现在强转为子类对象后,它就可以访问不属于自己的空间 _b,也就是越界访问了,所以是存在问题的。

所以说向下转换直接进行转换是不安全的!

所以C++提供了一种安全的类型转换方式:dynamic_cast,我们可以使用 dynamic_cast 对上面的代码进行修改:

				void func(A* pa)
				{
					B* ptr = dynamic_cast<B*>(pa);
					if (ptr)
					{
						cout << "转换成功" << endl;
						ptr->_a++;
						ptr->_b++;
					}
					else
					{
						cout << "转换失败" << endl;
					}
				}
				
				int main()
				{
					A a;
					B b;
					func(&a);
					func(&b);
				
					return 0;
				}

其中,dynamic_cast 会自动帮我们识别它之前是父类的对象还是子类的对象,从而帮我们实现转换,如果它之前是父类,现在转换为子类,那么就是不可以的,会转换失败,转换失败会返回空;如果它之前是子类,变成父类后又转换为子类,是可以的,就帮我们进行转换。dynamic_cast 还需要一个前提,就是父类必须要有虚函数。

对上面的代码进行测试,当传入父类的对象,转换失败:

【C++】类型转换,C++,c++,jvm,开发语言

当传入子类的对象,转换成功:

【C++】类型转换,C++,c++,jvm,开发语言

总结:文章来源地址https://www.toymoban.com/news/detail-807695.html

  1. dynamic_cast 只能用于父类含有虚函数的类
  2. dynamic_cast 会先检查是否能转换成功,能成功则转换,不能则返回 0.

到了这里,关于【C++】类型转换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++进阶(十五)C++的类型转换

    📘北尘_ :个人主页 🌎个人专栏 :《Linux操作系统》《经典算法试题 》《C++》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转

    2024年02月20日
    浏览(38)
  • C++强制类型转换

    static_cast 是 C++ 中的一种显式类型转换运算符。 它可以将一个表达式强制转换为指定的类型,并且是静态类型转换,因此不会执行任何运行时类型检查。如果类型转换不合法,则程序可能出现未定义的行为。因此,使用 static_cast 要特别小心,确保类型转换的合法性。 格式

    2024年02月07日
    浏览(71)
  • C++ 强制类型转换

    在C++中,有四种强制类型转换: 1、 static_cast :这是最常见的类型转换。它可以用于基本数据类型之间的转换,也可以用于指向父类和子类之间的指针或引用的转换。 static_cast可以实现下列转换: ①基本数据类型之间的转换。 ②将任何类型转换为void类型。 ③把空指针转换成

    2024年02月14日
    浏览(42)
  • C++的类型转换

    在C语言中,如果 赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就会发生类型转化 。 C语言总共有两种形式的类型转换: 隐式类型转换 和 显示类型转换 (强制类型转化) 隐式类型转化:编译器在编译阶段自动进行

    2024年02月16日
    浏览(34)
  • C++ 类型转换

    参与运算的多个操作数数据类型必须相同。 隐式类型转换 算术转换 赋值转换 输出转换 强制类型转换 简单强制类型转换 (type) 高级强制类型转换 static_cast dynamic_cast reinterpret_cast const_cast (type) 静态强制不检查、动态检查转派生、重新变型不检查、常量转变不变型。 4.2.1 stati

    2024年02月09日
    浏览(37)
  • C++——类型转换

    目录 一.C语言的类型转换 二.为什么需要C++的四种类型转换 三.C++强制类型转换 1.static_cast 2.reinterpret_cast 3.const_cast 4.dynamic_cast 在C语言中, 如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与 接收返回值类型不一致时,就需要发生类型转化 ,

    2024年02月06日
    浏览(30)
  • 【C++】类型转换

    在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化,C语言中总共有两种形式的类型转换: 隐式类型转换和显式类型转换 。 隐式类型转化 :编译器在编译阶段自动进行,能转就转,

    2024年01月20日
    浏览(37)
  • c++面试——强制类型转换

    方式 说明 示例 static_cast 用于基本类型之间、类继承体系之间的转换 int - double Derived* - Base* const_cast 用于移除变量的const、volatile等属性 const int - int dynamic_cast 用于类继承体系之间的安全向下转换,转换失败返回NULL Derived* - Base* reinterpret_cast 用于不相关类型之间的转换,结果不安

    2023年04月25日
    浏览(42)
  • 类型转换——C++

    在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化, C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换。 隐式类型转化:编译器在编译阶段自动进行,能转就转,不

    2023年04月20日
    浏览(34)
  • C++之类型转换

    目录 一、C语言中的类型转换 二、C++的强制类型转换  1、 static_cast 2、reinterpret_cast 3、 const_cast 4、dynamic_cast  在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化。 C语言中总共有两

    2024年02月07日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包