【初阶与进阶C++详解】第二十五篇:类型转换(static_cast+reinterpret_cast+const_cast+dynamic_cast+RTTI)

🏆个人主页企鹅不叫的博客

​ 🌈专栏

⭐️ 博主码云gitee链接:代码仓库地址

⚡若有帮助可以【关注+点赞+收藏】,大家一起进步!

💙系列文章💙

【初阶与进阶C++详解】第一篇:C++入门知识必备

【初阶与进阶C++详解】第二篇:C&&C++互相调用(创建静态库)并保护加密源文件

【初阶与进阶C++详解】第三篇:类和对象上(类和this指针)

【初阶与进阶C++详解】第四篇:类和对象中(类的六个默认成员函数)

【初阶与进阶C++详解】第五篇:类和对象下(构造+static+友元+内部类

【初阶与进阶C++详解】第六篇:C&C++内存管理(动态内存分布+内存管理+new&delete)

【初阶与进阶C++详解】第七篇:模板初阶(泛型编程+函数模板+类模板+模板特化+模板分离编译)

【初阶与进阶C++详解】第八篇:string类(标准库string类+string类模拟实现)

【初阶与进阶C++详解】第九篇:vector(vector接口介绍+vector模拟实现+vector迭代器区间构造/拷贝构造/赋值)

【初阶与进阶C++详解】第十篇:list(list接口介绍和使用+list模拟实现+反向迭代器和迭代器适配)

【初阶与进阶C++详解】第十一篇:stack+queue+priority_queue+deque(仿函数)

【初阶与进阶C++详解】第十二篇:模板进阶(函数模板特化+类模板特化+模板分离编译)

【初阶与进阶C++详解】第十三篇:继承(菱形继承+菱形虚拟继承+组合)

【初阶与进阶C++详解】第十四篇:多态(虚函数+重写(覆盖)+抽象类+单继承和多继承)

【初阶与进阶C++详解】第十五篇:二叉树搜索树(操作+实现+应用KVL+性能+习题)

【初阶与进阶C++详解】第十六篇:AVL树-平衡搜索二叉树(定义+插入+旋转+验证)

【初阶与进阶C++详解】第十七篇:红黑树(插入+验证+查找)

【初阶与进阶C++详解】第十八篇:map_set(map_set使用+multiset_multimap使用+模拟map_set)

【初阶与进阶C++详解】第十九篇:哈希(哈希函数+哈希冲突+哈希表+哈希桶)

【初阶与进阶C++详解】第二十篇:unordered_map和unordered_set(接口使用+模拟实现)

【初阶与进阶C++详解】第二十一篇:哈希应用(位图实现应用+布隆过滤器增删查优缺点+海量数据面试题)

【初阶与进阶C++详解】第二十二篇:C++11新特性(列表初始化+变量类型推到+右值引用+新增默认成员函数+可变模板参数+lambda表达式+包装器function_bind)

【初阶与进阶C++详解】第二十三篇:异常(异常抛出+异常捕获+异常优缺点)

【初阶与进阶C++详解】第二十四篇:智能指针(内存泄漏+RAII+auto_ptr+unique_ptr+shared_ptr+weak_ptr+定制删除器)



💎一、C语言中的类型转换

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

  • 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败
  • 显式类型转化:需要用户自己处理
void Test ()
{
	int i = 10;
	// 隐式类型转换
	double d = i;
	printf("%d, %.3f\n" , i, d);
	int* ptr = &i;
	// 显示的强制类型转换
	int address = (int) ptr;
	printf("%x, %d\n" , ptr, address);
}

缺陷:

  1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失
  2. 显式类型转换将所有情况混合在一起,代码不够清晰

💎二、C++强制类型转换

🏆1.static_cast

static_cast用于相近类型之间的类型转换

int main()
{
	double d = 13.14;
 //静态转换:static_cast
	//支持任何隐式类型转换  但它不支持两个不相关的类型进行强制转换
	int a = static_cast<int>(d);
	cout<<a<<endl;
	return 0;
}

🏆2.reinterpret_cast

reinterpret_cast用于不相近类型之间的类型转换

int main ()
{  

 int i = 10;
 //强制类型转换:reinterpret_cast
 //重新解释,用于将一种类型转换为另一种不同的类型
 int* pi = &i;
 int i2 = reinterpret_cast<int> (pi);
	return 0;
}

🏆3.const_cast

const_cast常用于删除变量的const属性,即用于将const变量转为非const变量,方便赋值

int main ()
{  
	const int ci = 10;
	const int* pci = &ci;
	int* pci2 = const_cast<int*> (&ci);
	*pci2 = 20;
	cout << ci << endl;   //10
	cout << *pci2 << endl;//20
	cout << *pci << endl; //20
	cout << "adress" << endl;  //下面三个地址都一样 编译器做了优化
	cout << &ci << endl;   
	cout << pci2 << endl;
	cout << pci << endl; 
 return 0;
}    

🏆4.dynamic_cast

dynamic_cast 用于将一个父类对象的指针转换为子类对象的指针或引用(动态转换)只能用于含有虚函数的父类(非多态不能使用dynamic_cast),规范向下转换,会检查是否能转换成功,能成功则转换,不能则返回0

  • 向上转型:子类对象指针->父类指针/引用(不需要转换,赋值兼容规则)
  • 向下转型:父类对象指针->子类指针/引用(用dynamic_cast转型是安全的)
class A
{
public:
	virtual void f(){}
};

class B : public A
{};
void fun(A* pa)
{
	B* ptr = dynamic_cast<B*>(pa);
    //用下面这两个转换,A转B,B转B都会成功,但是不安全
	//B* ptr = reinterpret_cast<B*>(pa);
	//B* ptr = (B*)pa;

	if (ptr)
	{
		cout << "转换成功" << ptr << endl;
	}
	else
	{
		cout << "转换失败" << ptr << endl;
	}
}

int main()
{
	A a;
	B b;
	fun(&a);//转换失败00000000,子类转换成父类,可能导致越界,不安全所以失败
	fun(&b);//转换成功(某个地址)
	return 0;
}

🏆5.explicit

explicit关键字阻止经过转换构造函数进行的隐式转换的发生

//explicit
class A
{
public:
	//explicit会阻止单参构造的隐式类型转换
 //编译器报错,不能从int类型转换到A类型
	explicit A(int a)
		:_a(a)
	{
		cout << "A(int a) " << endl;
	}
private:
	int _a;
};

int main()
{
	//explicit关键字会阻止单参构造函数进行的隐式转换
	A e = 10;
	return 0;
}

🏆6.RTTI

RTTI:Run-time Type identification的简称,即:运行时类型识别
C++通过以下方式来支持RTTI:

  1. typeid运算符(返回的是类型的字符串typeid(对象).name()
  2. dynamic_cast运算符
  3. decltype,获取对象具体类型

💎三、小结

  • 去const属性用const_cast
  • 基本类型转换用static_cast
  • 多态类之间的类型转换用dynamic_cast
  • 不同类型的指针类型转换用reinterpret_cast

强烈建议:避免使用强制类型转换


  • 14
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
C++中,四种类型的转换(有时也称为“cast”)用于处理不同数据类型的互相转换,它们各有特定的用途和使用场景。以下是这四种转换的简要说明以及它们在源代码中的基本实现: 1. **static_cast**:这是一种静态类型转换,用于明确且不涉及运行时类型的检查。它可以用于基本类型、指针、引用和内置的enum之间直接的转换。源代码示例: ```cpp int i = 5; double d = static_cast<double>(i); ``` 2. **dynamic_cast**:用于运行时类型检查,主要用于对象之间的类型转换,特别是当基类指针或引用需要转换为派生类类型时。如果类型转换成功,返回指向或引用的对象;否则返回null(对非指针)。例如: ```cpp class Base { ... }; class Derived : public Base { ... }; Base* baseObj = new Derived(); Derived* derivedObj = dynamic_cast<Derived*>(baseObj); ``` 3. **const_cast**:用于修改对象的const属性,即使在常量表达式中也可以用于临时去除const限定。这通常用于函数参数传递或返回值,或者为了修改const成员。注意这是有风险的,因为它打破了const契约: ```cpp const int& constRef = getConstInt(); int& mutableInt = const_cast<int&>(constRef); ``` 4. **reinterpret_cast**:这是最强大但也是最危险的转换,它将一个对象的数据重新解释为另一种类型,无视数据原有的字节布局。通常用于底层内存操作,如指针类型间的转换。不建议用于正常类型转换,仅在必要时使用,例如: ```cpp void* rawMemory = ...; // 假设我们知道它是int数组 int* intPtr = reinterpret_cast<int*>(rawMemory); ``` 请注意,这些类型转换在编译时就会进行,因此源代码中的实现主要体现在编译器层面,而不是直接在源码文件中看到具体的转换操作。实际的转换操作在C++库内部由编译器优化器处理。在代码中,我们主要关注的是转换的语法和意图。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

penguin_bark

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值