【C++高阶(九)】C++类型转换以及IO流

news2024/11/15 21:37:54

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C++从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习C++
  🔝🔝


在这里插入图片描述

C++高阶

  • 1. 前言
  • 2. C语言类型转换的方式
  • 3. C++的强制类型转换
  • 4. RTTI介绍(了解)
  • 5. C语言的输入输出和缓冲区
  • 6. C++IO流
  • 7. C++文件IO流
  • 8. 总结以及拓展

1. 前言

C语言中常见的类型转换有隐式类型
转换和强制转换,但是在面向对象的
语言中,这样使用未免太不优雅了!

本章重点:

本篇文章前半截着重讲解C++强制
转换的四种类型,以及为什么C++
需要自己设计一套类型转换.其中
会复习C语言的类型转换的方式.
后半截会讲解C++的IO流和文件IO
还会介绍string stream相关知识


2. C语言类型转换的方式

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

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

C语言类型转换的缺陷:

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

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


3. C++的强制类型转换

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

static_cast

reinterpret_cast

const_cast

dynamic_cast

下面将一一介绍它们的用法:

  1. static_cast

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

double d = 12.34;
int a = static_cast<int>(d);//将d强制转换为int类型
cout<< a <<endl;
  1. reinterpret_cast

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

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);
  1. const_cast

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

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

请注意,当你去测试这段代码时,确实不会报错,但是打印出来a的结果是2而不是3,*p的结果是3,这是因为当a被赋予const属性后,操作系统内部会做优化,每次使用a时会直接去寄存器中取,而不是去内存中取,显然,内存中的a已经被修改了!

在这里插入图片描述

  1. dynamic_cast

dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用

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

注意:

  1. dynamic_cast只能用于父类含有虚函数的类
  2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0
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转换只是安全的
并不代表一定能转换成功!


4. RTTI介绍(了解)

RTTI:Run-time Type identification
即:运行时类型识别

C++通过以下方式来支持RTTI:
1. typeid运算符
2. dynamic_cast运算符
3. decltype

这三种方式我们都学过了,RTTI
属于了解内容


5. C语言的输入输出和缓冲区

C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输入设备(键盘)读取数据,并将值存放在变量中。printf(): 将指定的文字/字符串输出到标准输出设备(屏幕)。注意宽度输出和精度输出控制。C语言借助了相应的缓冲区来进行输入与输出。如下图所示:

在这里插入图片描述

由于输入输出缓冲区是Linux系统
要学习的内容,所以这里就简单讲解

对输入输出缓冲区的理解:

  1. 可以屏蔽掉低级I/O的实现,低级I/O的实现依赖操作系统本身内核的实现,所以如果能够屏蔽这部分的差异,可以很容易写出可移植的程序。
  2. 可以使用这部分的内容实现“行”读取的行为,对于计算机而言是没有“行”这个概念,只有文件满了才会刷新,缓冲区的存在可以让用户有更好的体验,也就是行刷新

6. C++IO流

C++系统实现了一个庞大的类库
其中ios为基类
其他类都是直接或间接派生自ios类
在这里插入图片描述

C++标准库提供了4个全局流对象cin、cout、cerr、clog,使用cout进行标准输出,即数据从内存流向控制台(显示器)。使用cin进行标准输入即数据通过键盘输入到程序中,同时C++标准库还提供了cerr用来进行标准错误的输出,以及clog进行日志的输出,从上图可以看出,cout、cerr、clog是ostream类的三个不同的对象,因此这三个对象现在基本没有区别,只是应用场景不同。

  1. cin为缓冲流。键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中拿。如果一次输入过多,会留在那儿慢慢用,如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。只有把输入缓冲区中的数据取完后,才要求输入新的数据。
  2. 输入的数据类型必须与要提取的数据类型一致,否则出错。出错只是在流的状态字state中对应位置位(置1),程序继续。
  3. 空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输入。但如果是字符型和字符串,则空格(ASCII码为32)无法用cin输入,字符串中也不能有空格。回车符也无法读入。
  4. cin和cout可以直接输入和输出内置类型数据,原因:标准库已经将所有内置类型的输入和输出全部重载了
  5. 对于自定义类型,如果要支持cin和cout的标准输入输出,需要对<<和>>进行重载。

7. C++文件IO流

C++根据文件内容的数据格式分为二进制文件和文本文件。采用文件流对象操作文件的一般步骤:

  1. 定义一个文件流对象
    ifstream ifile(只输入用)
    ofstream ofile(只输出用)
    fstream iofile(既输入又输出用)
  2. 使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系
  3. 使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写
  4. 关闭文件
struct ServerInfo
{
	char _address[32];
	int _port;
	Date _date;	
};
struct ConfigManager
{
public:
ConfigManager(const char* filename)
	:_filename(filename)
{}
void WriteBin(const ServerInfo& info)
{
	ofstream ofs(_filename, ios_base::out | ios_base::binary);
	ofs.write((const char*)&info, sizeof(info));
}
void ReadBin(ServerInfo& info)
{
	ifstream ifs(_filename, ios_base::in | ios_base::binary);
	ifs.read((char*)&info, sizeof(info));
}
    // C++文件流的优势就是可以对内置类型和自定义类型,都使用
    // 一样的方式,去流插入和流提取数据
    // 当然这里自定义类型Date需要重载>> 和 <<
    // istream& operator >> (istream& in, Date& d)
      // ostream& operator << (ostream& out, const Date& d)
void WriteText(const ServerInfo& info)
{
	ofstream ofs(_filename);
	ofs << info._address << " " << info._port<< " "<<info._date;
}
void ReadText(ServerInfo& info)
{
	ifstream ifs(_filename);
	ifs >> info._address >> info._port>>info._date;
}
private:
	string _filename; // 配置文件
};
int main()
{
	ServerInfo winfo = { "192.0.0.1", 80, { 2022, 4, 10 } };
	// 二进制读写
	ConfigManager cf_bin("test.bin");
	cf_bin.WriteBin(winfo);
	ServerInfo rbinfo;
	cf_bin.ReadBin(rbinfo);
	cout << rbinfo._address << " " << rbinfo._port <<" "
	<<rbinfo._date << endl;
	// 文本读写
	ConfigManager cf_text("test.text");
	cf_text.WriteText(winfo);
	ServerInfo rtinfo;
	cf_text.ReadText(rtinfo);
	cout << rtinfo._address << " " << rtinfo._port << " " <<
	rtinfo._date << endl;
	return 0;
}

8. 总结以及拓展

本篇文章的内容不属于面试常考点,
但是了解了总比不了解号,没准面试官
问的偏,你这时就赢麻了(狗头)

拓展:

string stream的相关概念:

string stream介绍


🔎 下期预告:C++11线程库🔍

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

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

相关文章

Flask登陆后登陆状态及密码的修改和处理

web/templates/common 是统一布局 登录成功 后flask框架服务器默认由login.html进入仪表盘页面index.html(/),该页面的设置在 (web/controllers/user/index.py)&#xff0c;如果想在 该仪表盘页面 将 用户信息 展示出来&#xff0c;就得想办法先获取到 当前用户的 登陆状态。…

11、基于LunarLander登陆器的A2C强化学习(含PYTHON工程)

11、基于LunarLander登陆器的A2C强化学习&#xff08;含PYTHON工程&#xff09; LunarLander复现&#xff1a; 07、基于LunarLander登陆器的DQN强化学习案例&#xff08;含PYTHON工程&#xff09; 08、基于LunarLander登陆器的DDQN强化学习&#xff08;含PYTHON工程&#xff…

thinkcmf 文件包含 x1.6.0-x2.2.3 已亲自复现

thinkcmf 文件包含 x1.6.0-x2.2.3 CVE-2019-16278 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议总结 漏洞名称 漏洞描述 ThinkCMF是一款基于PHPMYSQL开发的中文内容管理框架&#xff0c;底层采用ThinkPHP3.2.3构建。ThinkCMF提出灵活的应用机制&a…

Elasticsearch中复制一个索引数据到新的索引中

问题 我有时候&#xff0c;需要调试一个已经存在的ES索引&#xff0c;需要从已有的索引复制数据到新的索引中去。 解决 这里我借助一个GUI工具&#xff0c;来解决这个问题&#xff0c;底层它是使用Reindex的API实现索引数据复制的。利用Reindex API搞不定这个事情&#xff0…

高德地图_公共交通路径规划API,获取两地点之间的驾车里程和时间

import pandas as pd import requests import jsondef get_dis_tm(origin, destination,city,cityd):url https://restapi.amap.com/v3/direction/transit/integrated?key xxx #这里就是需要去高德开放平台去申请key,请在xxxx位置填写,web服务APIlink {}origin{}&desti…

Laravel的知识点

1.{{ }} 是在 HTML 中内嵌 PHP 的 Blade 语法标识符&#xff0c;表示包含在该区块内的代码都将使用 PHP 来编译运行。 2.两种写法 3.return void 在这段注释中&#xff0c;"return void" 表示该函数或方法没有返回值。这意味着它执行某些操作或任务&#xff0c;但…

基于Java SSM框架实现县小吃门店连锁点餐订餐系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现县小吃门店连锁点餐订餐系统演示 摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 沙县小吃点餐系统&#xff0c;主要的模块包括实现管理员&#xff1b;个人中心、用户管…

根据commitID删除某一次提交

1.查看提交历史 git log --prettyoneline2.找到需要删除的那个commit,然后找到上次提交的commitID 比如想要删除下面这一条 我们找到上次提交的commitID 3.执行rebase git rebase -i efa11da0a684977bf8ac047ebb803e2ded2063a4 进入编辑状态显示如下 将需要删除的那个提交前…

基于Elemnet-plus 封装的功能表格,基本囊括element-plus 官网表格的所有使用场景

前言 这是一个多用途的基于element-plus 封装的表格组件&#xff0c;基本上elemnet-plus 官网涉及到的使用场景&#xff0c;都可以&#xff0c;而且使用上来说会简单许多&#xff0c;配置上类似与vxe-table 的使用&#xff0c;下面逐一展示各种场景的使用方式&#xff0c;基本上…

<JavaEE> TCP 的通信机制(三) -- 滑动窗口

目录 TCP的通信机制的核心特性 四、滑动窗口 1&#xff09;什么是滑动窗口&#xff1f; 2&#xff09;滑动窗口的作用是什么&#xff1f; 3&#xff09;批量传输出现丢包如何处理&#xff1f; 1> 接收端ACK丢包 2> 发送端数据包丢包 4&#xff09;适用性 TCP的通…

主动学习如何解决数据标注的难题?主动学习和弱监督学习有何区别?

机器学习的成功与否取决于数据标注的质量和数量。利用主动学习的机器学习技术能加快模型训练的进度和减少数据获取的资金投入。依靠主动学习来得到有价值的数据&#xff0c;以便机器模型从中学习。如果一个模型被具有价值的数据加以训练&#xff0c;它将以较少的人工标注和更短…

安防视频监控系统EasyCVR实现H.265视频在3秒内起播的注意事项

可视化云监控平台/安防视频监控系统EasyCVR视频综合管理平台&#xff0c;采用了开放式的网络结构&#xff0c;可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力&#xff0c;同时…

ZETA落地合肥、宜城南方水泥,纵行科技携手中才邦业助力水泥企业数智化管理

近日&#xff0c;合肥南方水泥、宜城南方水泥落地ZETA预测性维护方案&#xff0c;通过在水泥厂内搭建ZETA网络&#xff0c;并在B类及C类主辅机设备上安装ZETA系列端智能传感器&#xff0c;进行数据采集和监测设备运行状态、以及早期故障警报和诊断&#xff0c;实现水泥生产设备…

PHP的Laravel加一个小页面出现问题(whereRaw的用法)

1.权限更新问题 因为是已经有样例了所以html和php页面很快写出来了 然后就是页面写完了路由不知道在哪写&#xff0c;后来想起来之前有要开权限来着&#xff0c;试了一下&#xff0c;还是不行&#xff0c;不过方向是对了 这是加的路由&#xff0c;不过需要在更新一下权限 这…

零基础刷代码随想录【Day1】|| 二分查找,移除元素

我的个人主页&#xff1a;☆光之梦☆的博客_CSDN博客-C语言基础语法&#xff08;超详细&#xff09;领域博主 欢迎各位 &#x1f44d;点赞 ⭐收藏 &#x1f4dd;评论 我的专栏&#xff1a;C语言基础语法&#xff08;超详细&#xff09;_☆光之梦☆的博客-CSDN博客&#xff08;这…

Ubuntu安装K8S(1.28版本,基于containrd)

原文网址&#xff1a;Ubuntu安装K8S(1.28版本&#xff0c;基于containrd&#xff09;-CSDN博客 简介 本文介绍Ubuntu安装K8S的方法。 官网文档&#xff1a;这里 1.安装K8S 1.让apt支持SSL传输 sudo apt-get update sudo apt-get -y install apt-transport-https ca-certi…

【算法与数据结构】860、LeetCode柠檬水找零

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题的思路比较简单&#xff0c;首先要保存收到的零钱&#xff0c;其次计算找零&#xff0c;最后分解找…

git的常用命令以及在可视化工具中的使用方法

一.引言 想当初在刚进公司的时候&#xff0c;对于git的使用非常不熟悉&#xff0c;特别是分支的概念&#xff0c;导致开发效率变低&#xff0c;故通过此文章&#xff0c;总结git的使用经验 二.Git 常用命令详解 2.1 git clone [url]: 克隆远程仓库到本地 刚开始时&#xff0c…

Anaconda 环境中安装OpenCV (cv2)

1、使用Anaconda 的对应环境&#xff0c;查看环境中的Python版本号 (1)使用Anaconda 查看存在的环境&#xff1a;conda info --env (2)激活环境&#xff1a;conda activate XXX 2、根据版本号&#xff0c;下载对应的 python-opencv 包 &#xff08;1&#xff09;选择国内源的…

K8S网络类型

k8s的网络类型 k8s的通信模式 1 pod内部之间容器与容器之间的通信&#xff0c;在同一个pod中容器是共享资源和网络&#xff0c;使用同一个网络命名空间&#xff0c;可以直接通信 2 同一个node节点之内&#xff0c;不同pod之间的通信&#xff0c;每个pod都有一个全局的真实ip地…