学习->C++篇十七:C++的类型转换和IO流

目录

一.类型转换

1.C语言中的类型转换

2.C++中的类型转换

二.IO流

1. C语言的输入与输出

2. 流是什么

3. stringstream


一.类型转换

1.C语言中的类型转换

(1)隐式类型转换,编译阶段自动进行,不能转换就编译报错。(相关类型)

(2)强制类型转换,用户自行检查

例如:

缺点:转换的可读性差,显式类型转换的转换形式都相同,难以跟踪转换错误,隐式类型转换可能有精度丢失的问题。 

2.C++中的类型转换

为解决C语言类型转换的可读性,安全性的缺点,C++引入了四种命名的强制类型转换操作符。

(1)static_cast

用于相关类型之间的类型转换,非多态类型的转换,编译器执行的隐式类型转换都可以用static_cast,不相关的类型会编译报错,用法:

(2)reinterpret_cast

用于不相关类型的转换,例如上述的int类型的a转换为int*:

(3)const_cast

用于删除变量的const属性(const——cast中的类型必须是指针或引用):

这里两次打印出的a都是100,因为const常量取数据时被编译器优化了,没有到内存中取数据,而是优化到了寄存器,要防止这种优化,将变量用volatile关键字修饰,让每一次取数据a时,都强制到内存读取。例如:

 

(4)dynamic_cast

用于动态转换的向下转型。

向上转型:将子类指针或引用转换为父类指针或引用(安全的转换,赋值兼容,编译器原生支持)

向下转换:将父类指针或引用转换为子类指针或引用(不安全的转型,需用dynamic_cast)

注意:

1.dynamic_cast只能用于父类含有虚函数的类。

2.dynamic_cast 会先检查是否能转型成功,能转型成功就转换,反之返回0

例如:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>

using std::cout;
using std::endl;

class base
{
public:
	virtual void fun(){}
};

class derive:public base
{

};

void fun(base* b)
{
	derive* p1 = static_cast<derive*>(b);
	derive* p2 = dynamic_cast<derive*>(b);
	cout << p1 << endl;
	cout << p2 << endl << endl;
}
int main()
{
	base b;
	derive d;
	fun(&b);
	fun(&d);
	
	return 0;
}

输出:

 可见static_cast没有类型安全检查,而dynamic_cast有。

注意:dynamic_cast 是C++一种运行时类型识别的机制,即RTTI:Run-time Type identifification,还有两种方式,一种是typeid,一种是decltype。

二.IO流

1. C语言的输入与输出

C语言的常用输入和输出方式是scanf和printf,scanf:从标准输入( 键盘)中读取数据到变量中,
printf:将变量的值打印输出到标准输出(屏幕)中。C语言通过C语言提供的缓冲区来对输入和输出进行缓冲。
如图:
  缓冲区的作用
1.屏蔽掉低级IO的实现(封装系统调用),使代码可移植性更强。
2.使这部分的内容实现"行"读取的行为(C语言封装的)。

2. 流是什么

流:物质从一处往另一处流动。( 有序连续方向性数据的抽象描述)
C++的IO流:
C++实现了IO库,其中ios为基类,其他类直接或间接派生自ios类。
如图:
C++标准库提供了4个全局流对象cin(标准输入)、cout(标准输出)、cerr(标准错误的输出)、clog(日志的输出)。
使用注意:

### cin为缓冲流,键盘输入的数据会保存在我们的缓冲区当中,当要提取的时候会从缓冲区去拿。读取到回车的时候会刷新缓冲区。

### 空格和回车都作为数据之间的分隔符。

### cin和cout可以直接输入和输出所有内置类型,因为标准库已经全部重载了内置类型的输入输出函数。

### 对于自定义类型,如果要支持cin和cout的标准输入输出,需要对<<或>>进行重载。

### istream类型对象转换为逻辑条件判断值。- 类似于运算符重载。比如 while(cin>>i){}

### VS编译器下输入ctrl+z表示输入结束即eof

C++的文件IO流:

### 文件内容的数据格式有二进制文件和文本文件

### 文件流对象操作文件的步骤

- 定义文件流对象

- 使用对象成员函数打开磁盘文件

- 对文件进行读写操作或使用成员函数读写操作

- 关闭文件

使用示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<fstream>
using namespace std;

int main() 
{
	/*ifstream ifile(只输入用)
	ofstream ofile(只输出用)
	fstream iofile(既输入又输出用)*/
	string str = "hello world ,123456\n";
	ofstream ofs("text.txt");
	ofs << str;
	ofs.close();
 	return 0;
}

于是可以打开text.txt文件看到

 

3. stringstream

序列化与反序列化:
    将整形数据类型转换成字符串的数据类型的过程叫做序列化,反之叫做反序列化。

C与C++:
    在c语言中可以用这个itoa函数或者用sprintf函数进行转化
    在c++中可以使用stringstrem类对象进行转化

测试代码:

#include<iostream>
#include<string>
#include<sstream>
using namespace std;

int main()
{
	int num1 = 127863;
	string str;
	stringstream trans;
	trans << num1;
	trans >> str;
	cout << str << endl;

	//如果要进行多次转化需要用clear函数清空trans内部上次的转换状态
	trans.clear();
	double num2 = 898.19;
	trans << num2;
	trans >> str;
	cout << str << endl;

    //trans.str(""); 将底层string对象设置为""空字符串
	string s = trans.str();//返回trans对象中管理的string
	cout << s << endl;
	return 0;
}

输出:

 总结:

stringstream在其底层维护了一个string类型的对象用来保存结果。
多次数据类型转化时,需用clear()来清空,但clear()不会将 stringstream底层的string对象清空。
可使用s. str("")方法将底层string对象设置为""空字符串。
可使用s.str()将让stringstream返回其底层的string对象。
stringstream使用string类对象代替字符数组,可以避免缓冲区溢出的危险,不用格式化控制stringstream使用更方便,更安全。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值