C++四种基本类型转换

news2025/1/13 9:59:04

C++四种基本类型转换

  • 1.static_cast
  • 2.const_cast
  • 3.reinterpret_cast
  • 4 .dynamic_cast

1.static_cast

用法: static_cast<type_name> (expression)
说明:该运算符把expression转换为typen_name类型,static_cast在编译时使用类型信息执行转换,在转换执行必要的检测(诸如指针越界计算,类型检查等);但没有运行时类型检查来保证转换的安全性。
枚举是收到限制的整型,取值范围收到限制,枚举不能++
静态转换两者类型要兼容,而且不能去常性,但是可以加常性
无类型指针可以转成任意类型

基本类型转换

enum WeekType { sun = 0, mon = 1, ture = 2, wed = 3 };
int main()
{
	int a = 10;
	char ch = 'a';
	double dx = 12.23;
	//a = static_cast<int> (dx);
	ch = static_cast<char>(dx);
	WeekType x = sun;
	//x++;//error
	a = x;
	//x = a;//error
	x = static_cast<WeekType>(a);

	return 0;
}

在这里插入图片描述
指针转换的限制

int main(){
	int a = 10;
	int* p = &a;
	int* s = static_cast<int*>(&a); 
	int* s = nullptr;
	const int* cp = static_cast<const int*>(&a);
	//char* chp = static_cast<char*>(&a);//error
	//s = static_cast<int*>(cp);//error;静态转换类型必须一致
	s = const_cast<int*>(cp);

}

左值转右值

int main() {
	int a = 10;
	int &x= a;//左值

	//int&& rx = a;//error
	int&& rx = static_cast<int&&>(a);
	return 0;
}

rx x 都是a的别名

上下行转换

class Object {
private:
int value; public:
	Object(int x = 0) : value(x) {
		cout << "Create Object: " << endl;
	}
	~Object() {
		cout << "Destory 0bject" << endl;
	}

};
class Base : public Object {
private: int num; public:
	Base(int x = 0) : Object(x + 10), num(x) {
		cout << "Create Base " << endl;
	}
	 ~Base() {
		cout << "Destroy Base" << endl;
	}

};
int main() {
	Object* op = nullptr;
	Base* bp = nullptr;
	Base base;
	Object obj;
	op = &obj;
	bp = &base;

	op = bp;
	//bp = op;//error

	op = static_cast<Object*>(&base);
	bp = static_cast<Base*>(&obj);
	return 0;
}

bp = static_cast<Base*>(&obj);这里虽然可以编译,但是逻辑上是错误的,内存填充的是默认值,bp = op;//error这里直接就无法编译
上行转换安全,下行转换不安全

2.const_cast

用法:const_cast <type_name>(expression)
可以适用基本类型,也可以用在自己设计的类型
说明:该运算符用来修改类型的const或volatile属性。除了const或volatile修饰之外,typename和expression的类型是一样的。
特点:
1)用于去除变量的只读属性
2)强制转换的目标类型必须是指针或引用

int main() {
	int a = 10;
	const int* ap = &a;
	const int& ra = a;

	//int* ip = ap;
	//int& r = ra; 编译不通过

	int* ip = const_cast<int*>(ap);
	int& r = const_cast<int&>(ra);
}
class Int {
private:
	int value;
public:
	Int(int x = 0) :value(x) {
		cout << "Create Int" << endl;
	}
	~Int() {	}
	void SetValue(int x) {
		value = x;
	}
	int GetValue() const { return value; }

};
int main() {
	const int ca = 10;
	int* cap = const_cast<int*>(&ca);
	*cap = 20;
	cout << ca << endl;

	const Int a(10);
	//Int* p = &a;//error
	cout << a.GetValue() << endl;;
	Int* p = const_cast<Int*>(&a);
	p->SetValue(100);
	cout << a.GetValue() << endl;

	Int& aa = const_cast<Int&>(a);
	aa.SetValue(200);
	cout << a.GetValue() << endl;
}

由于ca是常整型,但是在编译的时候,ca已经被替换成了10,虽然它确实是变成了20,但是打印的还是10
而Int就不一样了,是常对象,去常性后,就可以修改

在这里插入图片描述

3.reinterpret_cast

用法: reinpreter_cast <type_name>(expression)
说明: type_name必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。类似C语言的强转。
特点:
不适用基本数据类型之间的转换
用于指针类型间的强制转换


int main() {
	int a = 0x61626364;
	//char* p = &a;//error
	char* p = reinterpret_cast<char*>(&a);
	cout << *p << endl;
	p += 1;
	cout << *p << endl;
	p += 1;
	cout << *p << endl;
	p += 1;
	cout << *p << endl;

	return 0;
}

p+1的能力跟指向的类型无关,根自己的类型有关
在这里插入图片描述

class Object {
private:
	int value;
public:
	Object(int x = 0) : value(x) { }
	~Object() {}
	int& Value() { return value; }
	const int& Value() const { return value; }
};

int main() {
	Object obj(10);
	int* p = reinterpret_cast<int*>(&obj);
	int& a = reinterpret_cast<int&>(obj);
	cout << obj.Value() << endl;
	*p = 100;
	cout << obj.Value() << endl;
	a = 200;
	cout << obj.Value() << endl;
	
	return 0;
}

在这里插入图片描述

对象和对象中的数据成员value是同一个地址

4 .dynamic_cast

语法: dynamic_cast <typen_ame> ( expression )
说明: dynamic_cast操作符,它允许在运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转换类型,把基类指针转换成派生类指针,或把指向基类的左值转换成派生类的引用。
必须是公有继承,基类要有虚函数。
特点:
1.与C++支持的其他强制转换不同的是,dynamic_cast是在运行时执行的类型转换。
⒉.如果针对指针类型的dynamic_cast失败,则dynamic_cast的结果是nullptr。
3.如果针对引用类型的dynamic_cast失败,则dynamic_cast会抛出一个异常。
4.在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的。
5.在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

class Object {
private:
	int value;
public:
	Object(int x=0):value(x){}
	~Object(){}
	virtual void func() { cout << "virtual Object func" << endl; }
	void fun() { cout << "Object fun"<<endl; }
};
class Base :public Object {
private:
	int num;
public:

	Base(int x=0):Object(x),num(x+10){ }
	~Base(){}
	virtual void func(){ cout << "virtual Base func" << endl; }
	void fun() { cout << "Base fun" << endl; }
};

int main() {
	Object* op1 = nullptr, * op2 = nullptr;
	Object obj(10);
	Base* bp = nullptr;
	Base base(10);
	op1 = &base;
	op2 = &obj;

	op1->fun();
	op1->func();
	op2->fun();
	op2->func();

	bp = dynamic_cast<Base*>(op1);
	bp->fun();
	bp->func();
	return 0;
}

总结:
Object* op1 = nullptr, op1 = &base; op1在用静态函数时,他就是Object*, 但是有虚函数时,就是Base*,通过动态转换Base* bp = nullptr;, bp = dynamic_cast<Base*>(op1); op1在用静态函数时,和虚函数时,都就是Base*
在这里插入图片描述


int main() {
	Object* op1 = nullptr, * op2 = nullptr;
	Object obj(10);
	Base* bp = nullptr;
	Base base(10);
	op1 = &base;
	op2 = &obj;
	//指针类型信息
	cout << typeid(op1).name() << endl;
	cout << typeid(op2).name() << endl;
	cout << typeid(*op1).name() << endl;
	cout << typeid(*op2).name() << endl;
	
	op1->fun();
	op1->func();
	op2->fun();
	op2->func();

	//op1指向&base,可以动态转换
	bp = dynamic_cast<Base*>(op1);
	bp->fun();
	bp->func();

	//op1指向&obj,不可以动态转换
	bp = dynamic_cast<Base*>(op2);
	if (bp == nullptr) {
		cout << "bp==nullptr" << endl;
	}
	else bp->func();
	return 0;
}

typeid(*op1).name() 能知道指针所指之物是存储了类型识别信息
在这里插入图片描述
这里下行转换,就不行
在这里插入图片描述

int main() {
	
	Object obj(10);
	Base* bp = nullptr;
	Base base(10);
	Object* op1 = &base;
	Object* op2 = &obj;
	//Base* bp1 = &obj;//err
	Base* bp1 = static_cast<Base*>(&obj);
	Base* bp2 = &base;
	bp1->fun();
	bp1->func();
	bp2->fun();
	bp2->func();

	return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/679410.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring事务源码详解-spring原码(一)

前面说过了aop源码&#xff0c;这里再稍微回顾一下 我们会用注解EnableAspectJautoProxy开启aop 当我们用了proxytargetClass会强制cglib动态代理 源码里有Import 里面会注册AnnotionAwareAspectJAutoProxyCreator 后面会在beanDefinationMap获取到所有定义的Objects循环 …

2020新基建决赛-crypto-onepiece

onepiece 一、概要 1、标题&#xff1a;onepiece 2、关键字&#xff1a;e2&#xff0c;rabin&#xff0c;凯撒 3、比赛&#xff1a;2020新基建决赛 4、工具&#xff1a;python&#xff0c;米斯特工具 二、开始 1、题目分析 题目给了一个pubkey.pem和onepiece.enc&#xff…

C++右值引用 移动语义 完美转发 引用叠加

右值引用 MyString浅拷贝与深拷贝浅赋值与深赋值 左值与右值左值概念左值右值与函数的结合移动构造函数移动赋值函数移动构造和移动赋值的应用 移动语义 有点问题完美转发引用叠加 MyString 浅拷贝与深拷贝 s1先在堆区申请了空间&#xff0c;然后将p指针指向的字符串复制到该…

设计模式之责任链模式笔记

设计模式之责任链模式笔记 说明Chain of Responsibility(责任链)目录责任链模式示例类图请假条类抽象处理者类小组长类部门经理类总经理类测试类 说明 记录下学习设计模式-责任链模式的写法。JDK使用版本为1.8版本。 Chain of Responsibility(责任链) 意图:使多个对象都有机…

Vue搜索组件,显示热门、近期搜索(结合element ui)

&#x1f680; 注重版权&#xff0c;转载请注明原作者和原文链接 &#x1f96d; 作者&#xff1a;全栈小袁 &#x1f34e; 原创个人开源博客项目(目前V3.0版本)&#xff1a;https://github.com/yuanprogrammer/xiaoyuanboke &#x1f349; 开源项目觉得还行的话点点star&#x…

【P4】Windows 下搭建 DVWA 及命令注入漏洞详解

文章目录 一、Windows 下搭建 DVWA1.1、DVWA 靶场搭建1.2、六步快速搭建 DVWA1.2.1、下载并安装 PHPstudy&#xff1a;http://public.xp.cn/upgrades/PhpStudy2018.zip1.2.2、将解压后的 DVWA 原代码放置 phpstudy 安装目录的 WWW文件夹1.2.3、进入 DVWA/config 目录&#xff0…

2022前端趋势报告(下)

前端博主&#xff0c;热衷各种前端向的骚操作&#xff0c;经常想到哪就写到哪&#xff0c;如果有感兴趣的技术和前端效果可以留言&#xff5e;博主看到后会去代替大家踩坑的&#xff5e; 主页: oliver尹的主页 格言: 跌倒了爬起来就好&#xff5e; 一、前言 本文内容来自于《St…

springBoot学习——spring+springMVC 集成mybatis 拦截器

目录 引出入门案例&#xff1a;登陆和注册 & 用户信息分页 之 固定的步骤&#xff1a;&#xff08;1&#xff09;建普通项目配置pom.xml文件&#xff08;2&#xff09;写主启动类 application.yml文件【bug】pom.xml文件导了mybatis的包&#xff0c;但是application.yml文…

Drag Your GAN论文解读,基于点的交互式操作拖动到生成图像[DragGAN]

只需要鼠标的点击就可以自动修图的产品&#xff0c;火爆问世&#xff0c;可以说是超越PS&#xff0c;神一般的存在了&#xff0c;而且没有门槛&#xff0c;对于普通大众来说直接可以上手使用&#xff0c;这个是PS完全不具备的。更关键的是&#xff0c;这款产品跟PS明显区别在于…

如何系统地自学 Python?

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言为什么选择Python作…

【Intel 黑客松大赛】基于YOLO的杂草-农作物检测分类系统

目录 一、赛题简介&#xff1a;计算机视觉挑战——检测并清除杂草二、基于YOLO的杂草-农作物检测分类2.1、YOLO简介2.2、基于YOLO的杂草-农作物检测分类解决方案 三、基于YOLO的杂草-农作物检测分类系统设计3.1、基于flask框架的demo应用程序后端3.2、基于Vue框架的demo应用程序…

Qt6.2教程——4.QT常用控件QPushButton

一&#xff0c;QPushButton简介 QPushButton是Qt框架中的一种基本控件&#xff0c;它是用户界面中最常见和最常用的控件之一。QPushButton提供了一个可点击的按钮&#xff0c;用户可以通过点击按钮来触发特定的应用程序操作。比如&#xff0c;你可能会在一个对话框中看到"…

Unity编辑器扩展-第七集-应用键/显示提示词

第六集链接&#xff1a;Unity编辑器扩展-第六集-创建窗口/批量填图_菌菌巧乐兹的博客-CSDN博客 一、本节目标效果展示 1.我们有时候需要多次使用编辑窗口&#xff0c;但是每次一点执行&#xff0c;就关掉了&#xff0c;就很烦&#xff0c;所以我们希望&#xff0c;点击按钮&…

Spring Bean的实例化过程

一、前言 对于写Java的程序员来说&#xff0c;Spring已经成为了目前最流行的第三方开源框架之一&#xff0c;在我们充分享受Spring IOC容器带来的红利的同时&#xff0c;我们也应该考虑一下Spring这个大工厂是如何将一个个的Bean生产出来的&#xff0c;本期我们就一起来讨论一…

2023年6月GESP能力等级认证Python一级真题

2023-06 GESP等级考Python一级真题 题数&#xff1a;27 分数&#xff1a;100 测试时长&#xff1a;90min 一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 1. 以下不属于计算机输出设备的有&#xff08; A&#xff09;。&#xff08;2分&#xff09; A…

几个Arcpy代码应用案例

1 案例一 删除特定记录 使用 arcpy 从 ArcGIS 中的图层中删除特定记录。可以使用更新游标&#xff08;UpdateSursor&#xff09;和 SQL 查询来识别和删除所需的记录。以下是如何删除特定图层记录的示例 import arcpy selectedParcelsselectedParcels expres…

分子碰撞频率和自由程------从一个物理小问题解剖自己的数学思维

物理学12-8节中&#xff0c;关于分子平均碰撞的解说如下&#xff1a; &#xff08;一&#xff09;分子碰撞自由程公式 第一个公式中&#xff0c;lamda v / z中&#xff0c;v的单位是m/s, z的单位是A/s, 其中A是常数。那么lamda描述的结果是m/A, 这正是长度单位。 此公式lamda…

利用正弦定理证明两角和差公式

首先用正弦定理&#xff0c;证明sin(AB)sinAcosBcosAsinB。 另外&#xff0c;其它的两角和差公式&#xff0c;都可以用三角函数奇偶性、诱导公式等推导出来&#xff0c;无需再用正弦定理证明一遍。

耗时一个月!手撸博客系统,主打美观实用!

先附上博客链接RoCBlog 关于博客 关于博客 RoCBlog 完成耗时&#xff1a;20天 起初是想搭建自己的博客&#xff0c;看了网上许多开源框架&#xff0c;感觉没啥意思&#xff0c;于是决定自己写一套 纯手撸VueSpringboot 其实是个我一边学vue一边写出来的东西&#xff0c;前期…

团体程序设计天梯赛-练习集L1篇⑩

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的普通人。 &#x1f3c0;个人主页&#xff1a;陈童学哦CSDN &#x1f4a1;所属专栏&#xff1a;PTA &#x1f381;希望各…