C++的类型转换

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

C++的类型转换

收录于专栏 [C++进阶学习]
本专栏旨在分享学习C++的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

1. C语言中的类型转换 

2. C++四种强制类型转换 

2.1 static_cast

2.2 reinterpret_cast

2.3 const_cast

2.4 dynamic_cast

3. 为什么C++需要四种类型转换

4. RTTI

typeid 操作符:

dynamic_cast 操作符:

5. C++类型转换总结  


1. C语言中的类型转换 

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

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

#include <stdio.h>

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);
}

int main()
{
    Test();
    return 0;
}

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

2. C++四种强制类型转换 

2.1 static_cast

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

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

2.2 reinterpret_cast

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

int main()
{
    double d = 12.34;
    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);
    return 0;
}

2.3 const_cast

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

#include <stdio.h>
#include <iostream>
using namespace std;

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


int main()
{
    Test();
    return 0;
}

2.4 dynamic_cast

dynamic_cast用于将一个父类对象的指针 / 引用转换为子类对象的指针或引用(动态转换)
向上转型:子类对象指针 / 引用->父类指针 / 引用(不需要转换,赋值兼容规则)
向下转型:父类对象指针 / 引用->子类指针 / 引用(用dynamic_cast转型是安全的)

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

#include <iostream>
using namespace std;

class A
{
public:
	virtual void f() {}
};

class B : public A
{};

void fun(A* pa)
{
	B* pb1 = static_cast<B*>(pa);
	B* pb2 = dynamic_cast<B*>(pa);

	if (pb1 == nullptr) {
		cout << "pb1 is nullptr (static_cast) - potential unsafe cast!" << endl;
	}
	else {
		cout << "pb1 (static_cast): " << pb1 << endl;
	}

	if (pb2 == nullptr) {
		cout << "pb2 is nullptr (dynamic_cast) - cast failed!" << endl;
	}
	else {
		cout << "pb2 (dynamic_cast): " << pb2 << endl;
	}
}

int main()
{
	A a;  // A 类型的对象
	B b;  // B 类型的对象
	fun(&a);  // 传递 A 类型的对象
	fun(&b);  // 传递 B 类型的对象
	return 0;
}

注意
强制类型转换关闭或挂起了正常的类型检查,每次使用强制类型转换前,程序员应该仔细考虑是否还有其他不同的方法达到同一目的,如果非强制类型转换不可,则应限制强制转换值的作用域,以减少发生错误的机会。强烈建议:避免使用强制类型转换

3. 为什么C++需要四种类型转换

C风格的转换格式很简单,但是有不少缺点的:
1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失
2. 显式类型转换将所有情况混合在一起,代码不够清晰

因此C++提出了自己的类型转化风格,注意因为C++要兼容C语言,所以C++中还可以使用C语言的
转化风格。

4. RTTI

RTTI(Runtime Type Identification,运行时类型识别)是 C++ 中的一种机制,允许在运行时确定对象的动态类型。它主要通过 typeid 运算符和 dynamic_cast

typeid 操作符:

返回一个表示类型信息的 type_info 对象,可以通过它获取对象的类型名称等信息。

#include <iostream>
#include <typeinfo>

class A {};
class B : public A {};

int main() {
    A a;
    B b;
    std::cout << typeid(a).name() << std::endl;  // 输出 A 的类型名
    std::cout << typeid(b).name() << std::endl;  // 输出 B 的类型名
    A* pa = &b;
    std::cout << typeid(*pa).name() << std::endl; // 输出 B 的类型名
    return 0;
}

dynamic_cast 操作符:

用于安全地进行类型转换,特别是在多态类的情况下。dynamic_cast 能够检查转换是否有效,如果转换失败,则返回 nullptr(对于指针)或抛出 std::bad_cast 异常(对于引用)。 

B* pb = dynamic_cast<B*>(pa);  // 如果 pa 指向 B 的实例,pb 将有效;否则,pb 为 nullptr。

 RTTI 是 C++ 中的重要特性,允许程序在运行时进行类型识别和安全的类型转换。这对于使用多态的面向对象编程模式尤为重要,有助于编写更安全和灵活的代码。

5. C++类型转换总结  

在 C++ 中,有四种主要的类型转换方式,它们分别是:

隐式转换(Implicit Conversion)
显式转换(Explicit Conversion),通常使用类型转换运算符。
static_cast
dynamic_cast
const_cast
reinterpret_cast

 各个转换的应用场景:

1. 隐式转换(Implicit Conversion)
应用场景:在需要自动进行类型转换的情况下,例如将 int 类型赋值给 float 类型时,编译器会自动进行转换。这种转换可以减少代码的复杂性。
2. 显式转换(Explicit Conversion)
应用场景:当你想要控制类型转换的行为时,可以使用显式转换。特别是在将不同类型的数据进行混合计算时,确保转换是安全的。
3. static_cast
应用场景:在进行较为简单的转换时,比如基类指针到派生类指针的转换(在编译时已知对象类型)或基本数据类型之间的转换。static_cast 不会执行运行时检查。
4. dynamic_cast
应用场景:在涉及多态的情况下,当你需要安全地将基类指针转换为派生类指针时使用,尤其是当你不确定对象的实际类型时。dynamic_cast 在运行时检查类型安全。
5. const_cast
应用场景:用于修改对象的常量性,例如从一个 const 对象获取非 const 指针。常用于需要改变某个函数参数的常量性时。
6. reinterpret_cast
应用场景:进行低级别的类型转换,例如将指针类型转换为其他不相关类型的指针。通常用于与硬件或内存映射等底层操作时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值