先写写关于IO标准库。
1. iostream:
iostream为内置类型类型对象提供了输入输出支持,同时也支持文件的输入输出,类的设计者可以通过对iostream库的扩展,来支持自定义类型的输入输出操作。
#include < iostream >
using namespace std;
class Test
... {
public:
Test(int a=0,int b=0)
...{
Test::a=a;
Test::b=b;
}
int a;
int b;
} ;
int main()
... {
Test t(100,50);
printf("%???",t);//不明确的输出格式
scanf("%???",t);//不明确的输入格式
cout<<t<<endl;//同样不够明确
cin>>t;//同样不够明确
return 0;
}
由于自定义类的特殊性,在上面的代码中,无论你使用c风格的输入输出,或者是c++的输入输出都不是不明确的一个表示,由于c语言没有运算符重载机制,导致stdio库的不可扩充性,让我们无法让printf()和scanf()支持对自定义类对象的扩充识别,而c++是可以通过运算符重载机制扩充 iostream库的,使系统能能够识别自定义类型,从而让输入输出明确的知道他们该干什么,格式是什么。
2. iostream: istream 和 ostream
我们所熟悉的输入输出操作分别是由istream(输入流)和ostream(输出流)这两个类提供的,为了允许双向的输入/输出,由istream和ostream派生出了iostream类。
类的继承关系见下图:
iostream库定义了以下三个标准流对象:
- cin,表示标准输入(standard input)的istream类对象。cin使我们可以从设备读如数据。
- cout,表示标准输出(standard output)的ostream类对象。cout使我们可以向设备输出或者写数据。
- cerr,表示标准错误(standard error)的osttream类对象。cerr是导出程序错误消息的地方,它只能允许向屏幕设备写数据。
输出主要由重载的左移操作符(<<)来完成,输入主要由重载的右移操作符(>>)完成:
- >>a表示将数据放入a对象中。
- <<a表示将a对象中存储的数据拿出。
这些标准的流对象都有默认的所对应的设备,见下表:
C++对象名 | 设备名称 | C中标准设备名 | 默认含义 |
---|---|---|---|
cin | 键盘 | stdin | 标准输入 |
cout | 显示器屏幕 | stdout | 标准输出 |
cerr | 显示器屏幕 | stderr | 标准错误输出 |
那么原理上C++有是如何利用cin/cout对象与左移和右移运算符重载来实现输入输出的呢?
下面我们以输出为例,说明其实现原理:
- cout是ostream类的对象,因为它所指向的是标准设备(显示器屏幕),所以它在iostream头文件中作为全局对象进行定义。
- ostream cout(stdout);//其默认指向的C中的标准设备名,作为其构造函数的参数使用。
- 在iostream.h头文件中,ostream类对应每个基本数据类型都有其友元函数对左移操作符进行了友元函数的重载。
- ostream& operator<<(ostream &temp,int source);
- ostream& operator<<(ostream &temp,char *ps);
- ... 等等
一句输出语句:cout<<"www.cndev-lab.com";,事实上调用的就是ostream& operator<<(ostream &temp,char *ps);这个运算符重载函数,由于返回的是流对象的引用,引用可以作为左值使用,所以当程序中有类似cout<<"www.cndev- lab.com"<<"中国软件开发实验室";这样的语句出现的时候,就能够构成连续输出。
由于iostream库不光支持对象的输入输出,同时也支持文件流的输入输出,所以在详细讲解左移与右移运算符重载只前,我们有必要先对文件的输入输出以及输入输出的控制符有所了解。