跨境派

跨境派

跨境派,专注跨境行业新闻资讯、跨境电商知识分享!

当前位置:首页 > 卖家故事 > 【C++高阶(九)】C++类型转换以及IO流

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

时间:2024-04-13 15:50:21 来源:网络cs 作者:晨起 栏目:卖家故事 阅读:

标签: 转换  类型 
阅读本书更多章节>>>>

💓博主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语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换。

隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败
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);

C语言类型转换的缺陷:

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

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


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

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

static_castreinterpret_castconst_castdynamic_cast

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

static_cast

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

double d = 12.34;int a = static_cast<int>(d);//将d强制转换为int类型cout<< a <<endl;
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);
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已经被修改了!

在这里插入图片描述

dynamic_cast

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

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

注意:

dynamic_cast只能用于父类含有虚函数的类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系统
要学习的内容,所以这里就简单讲解

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

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

6. C++IO流

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

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

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

7. C++文件IO流

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

定义一个文件流对象
ifstream ifile(只输入用)
ofstream ofile(只输出用)
fstream iofile(既输入又输出用)使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写关闭文件
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线程库🔍
阅读本书更多章节>>>>

本文链接:https://www.kjpai.cn/gushi/2024-04-13/158137.html,文章来源:网络cs,作者:晨起,版权归作者所有,如需转载请注明来源和作者,否则将追究法律责任!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。

文章评论