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

💓博主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_castreinterpret_castconst_castdynamic_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.hqwc.cn/news/303498.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

柯桥学会计,专业会计培训,会计人年底常用工作清单

01 盘点现金和核对银行存款 1️⃣ 库存现金 现金账上不能出现负数&#xff1b;核对现金账面余额是否与库存现金相符&#xff1b;库存现金是否超过限额规定。 2️⃣ 银行存款#15857575376 核对银行存款日记账与银行对账单是否相符&#xff1b;检查银行账户是否有未达账项&#x…

除法计算器 C语言xdoj48

问题描述 小明的弟弟刚开始学习除法&#xff0c;为了检查弟弟的计算结果是否正确&#xff0c;小明决定设计一个简单计算器程序来验算。 输入说明 输入数据由四个整数m&#xff0c;n&#xff0c;q&#xff0c;r构成&#xff0c;m为被除数&#xff0c;n为除数&#xff0c…

Pandas教程(三)—— 数据清洗与准备

1.处理缺失值 1.1 数据删除函数 作用&#xff1a;删除Dataframe某行或某列的数据 语法&#xff1a;df.drop&#xff08; labels [ ] &#xff09; drop函数的几个参数&#xff1a; labels &#xff1a;接收一个列表&#xff0c;内含删除行 / 列的索引编号或索引名 axis &…

扫码看视频时能加封面图吗?设置封面的视频码做法

制作视频二维码时&#xff0c;能给视频加入一个封面图吗&#xff1f;为了让视频展示的更加美观&#xff0c;很多人会想要给视频加上一个封面图&#xff0c;但是很多的二维码生成器无法实现这个功能&#xff0c;那么如何制作可添加封面图的视频二维码呢&#xff1f;本文将给大家…

【基础篇】六、自定义类加载器打破双亲委派机制

文章目录 1、ClassLoader抽象类的方法源码2、打破双亲委派机制&#xff1a;自定义类加载器重写loadclass方法3、自定义类加载器默认的父类加载器4、两个自定义类加载器加载相同限定名的类&#xff0c;不会冲突吗&#xff1f;5、一点思考 1、ClassLoader抽象类的方法源码 ClassL…

【量化】蜘蛛网策略复现

文章目录 蜘蛛网策略研报概述持仓数据整理三大商品交易所的数据统一筛选共有会员清洗数据计算研报要求数据全部代码 策略结果分析无参数策略有参数策略正做反做 MSD技术指标化 蜘蛛网策略 策略来自《东方证券-股指期货趋势交易之蜘蛛网策略——从成交持仓表中捕捉知情投资者行为…

Python - 深夜数据结构与算法之 Divide Conquer Backtrack

目录 一.引言 二.分治与回溯简介 1.Divide & Conquer 分治 2.BackTrack 回溯 三.经典算法实战 1.Combination-Of-Phone [17] 2.Permutations [46] 3.Permutations-2 [47] 4.Pow-X [50] 5.N-Queen [51] 6.Combinations [78] 7.Sub-Sets [78] 8.Majority-Elemen…

系列八、VMWare无法启动CentOS7问题排查 解决

一、VMWare无法启动CentOS7 1.1、问题描述 今天在测试代码的时候&#xff0c;需要用到Linux&#xff0c;然后就打开VMWare进行启动&#xff0c;但是启动的时候发现无法启动起来&#xff0c;报了一个如下的错误&#xff1a; 出现了问题那就要解决问题&#xff0c;然后想起来前几…

Kruskal(克鲁斯卡尔)算法总结

知识概览 克鲁斯卡尔算法适用于稀疏图求最小生成树&#xff0c;时间复杂度为O(mlogm)。 例题展示 题目链接 Kruskal算法求最小生成树 859. Kruskal算法求最小生成树 - AcWing题库https://www.acwing.com/problem/content/861/ 代码 #include <iostream> #include &l…

C语言实验1:C程序的运行环境和运行C程序的方法

一、算法原理 这是学C语言的入门&#xff0c;并不需要很高深的知识&#xff0c;一个hello world 或者一个简单的加法即可 二、实验要求 了解所用的计算机系统的基本操作方法&#xff0c;学会独立使用该系统。 了解在该系统上如何编辑、编译、连接和运行一个C程序。 通过运…

Sectigo和Certum的IP证书区别

IP证书是比较特别的一款数字证书。大多数SSL数字证书都是针对域名站点的数字证书&#xff0c;比如单域名SSL证书、多域名SSL证书和通配符SSL证书&#xff0c;而IP证书针对的是只拥有公网IP地址的站点。签发IP证书的CA认证机构并不多&#xff0c;Sectigo和Certum旗下都有IP证书&…

【51单片机系列】DS1302时钟模块

本文是关于DS1302时钟芯片的相关介绍。 文章目录 一、 DS1302时钟芯片介绍二、DS1302的使用2.1、DS1302的控制寄存器2.2、DS1302的日历/时钟寄存器2.3、片内RAM2.4、DS1302的读写时序 三、SPI总线介绍四、DS1302使用示例 一、 DS1302时钟芯片介绍 DS1302是DALLAS公司推出的涓流…