cout/cin

转载来源:http://baike.baidu.com/link?url=NiNaSw0pF7RqFO8u0jx8KWk9yOfFFYy24xCJlQ6_qMcw5_WBzRKOqsO6tfvvJbZMhr_ZQJfILUPBXq2ArS9Mg_

对于cin、cout,说到底还是函数调用,不过这函数有些特殊,用的是运算符重载,确切地说(以下还是以cout为例)是重载了“<<”运算符。我们就让它现出函数的本来面目,请看HelloWorld!的等效版本:

#include<iostream>
using namespace std;
int main()
{
    cout.operator << ("Hello,World!");
    cout.operator << (endl);
    return 0;
}

编译运行,结果与经典版无二。上面程序应该更容易理解了:cout是一个ostream类的对象,它有一个成员运算符函数operator<<,每次调用的时候就会向输出设备(一般就是屏幕啦)输出东东。嗯,这里有一个问题:为什么函数operator<<能够接受不同类型的数据,如整型浮点型、字符串甚至指针,等等呢?

我想你已经猜到了,没错,就是用运算符重载运算符函数与一般函数基本无异,可以任意重载。标准库的设计者们早已经为我们定制了iostream::operator<<对于各种C++基本数据类型的重载版本,这才使得我们这些初学者们一上来就享受到

cout<<"Hello,World!"<<endl;
cout.operator<<("Hello,World!").operator<<(endl);

才算“强等效”。究竟可不可以这样写?向编译器确认一下……OK,NoProblem!

对于cin,则是istream流类的对象,其重载了>>运算符,用法与cout大致相同

实现原理:

嗯,我们已经基本上看出了cout的实质,不妨动动手,自己来实现一个cout的简化版(Lite),为了区分,我们把我们设计的cout对象命名的myout,myout对象所属的类为MyOutstream。我们要做的就是为MyOutstream类重载一系列不同类型的operator<<运算符函数,简单起见,这里我们仅实现了对整型(int)与字符串型(char*)的重载。为了表示与iostream断绝关系,我们不再用头文件iostream,而使用古老的stdio中的printf函数进行输出,程序很简单,包括完整的main函数,均列如下:

#include//在C和一些古老的C++中是stdio.h,新标准为了使标准库

//的头文件与用户头文件区别开,均推荐使用不用扩展名

//的版本,对于原有C库,不用扩展名时头文件名前面要加c

class MyOutstream
{
public:
    const MyOutstream& operator << (intvalue)const;//对整型变量的重载
    const MyOutstream& operator << (char*str)const;//对字符串型的重载
};
const MyOutstream& MyOutstream::operator<<(intvalue)const
{
    printf("%d",value);
    return* this;//注意这个返回……
}
const MyOutstream& MyOutstream::operator << (char* str)const
{
    printf("%s",str);
    return* this;//同样,这里也留意一下……
}
MyOutstream myout;//随时随地为我们服务的全局对象myout
int main()
{
    int a=2003;
    char* myStr="Hello,World!";
    myout << myStr << "\n";
    return 0;
}

我们定义的myout已经初具形态,可以为我们工作了。程序中的注释指出两处要我们特别注意的:即是operator<<函数执行完毕之后,总是返回一个它本身的引用,输出已经完成,为何还要多此一举?

还记得那个有点奇异的cout.operator<<("Hello,World!").operator<<(endl)么?它能实现意味着我们可以连着书写

cout<<"Hello,World!"<<endl;

而不是

cout<<"Hello,World!";
cout<<endl;

为何它可以这样连起来写?我们分析一下:按执行顺序,系统首先调用cout.operator<<("Hello,World!"),然后呢?然后cout.operator<<会返回它本身,就是说在函数的最后一行会出现类似于return *this这样的语句,因此cout.operator<<("Hello,World!")的调用结果就返回了cout,接着它后面又紧跟着.operator<<(endl),这相当于cout.operator<<(endl)——于是又会进行下一个输出,如果往下还有很多<<算符,调用就会一直进行……哇噢,是不是很聪明?现在你明白我们的MyOutstream::operator<<最后一行的奥妙了吧!

再注意一下main函数中最激动人心的那一行:

myout<<"\n"

我们知道,最后出现的"\n"可以实现一个换行,不过我们在用C++时教程中总是有意无意地让我们使用endl,两者看上去似乎一样——究竟其中有什么玄妙?查书,书上说endl是一个操纵符(manipulator),它不但实现了换行操作,而且还对输出缓冲区进行刷新。什么意思呢?原来在执行输出操作之后,数据并非立刻传到输出设备,而是先进入一个缓冲区,当适宜的时机(如设备空闲)后再由缓冲区传入,也可以通过操纵符flush,ends,或unitbuf进行强制刷新:

cout<<"Hello,World!"<<"Flush the screen now!!!"<<flush;

这样当程序执行到operator<<(flush)之前,有可能前面的字符串数据还在缓冲区中而不是显示在屏幕上,但执行operator<<(flush)之后,程序会强制把缓冲区的数据全部搬运到输出设备并将其清空。而操纵符endl相当于<<"\n"<<flush;

不过可能在屏幕上显示是手动刷新与否区别看来都不大。但对于文件等输出对象就不大一样了:过于频繁的刷新意味着老是写盘,会影响速度。因此通常是写入一定的字节数后再刷新,如何操作?靠的就是这些操纵符。

时间: 2024-08-25 02:29:11

cout/cin的相关文章

Qt中使用cout, cin, cerr

在Qt中,用的最多的是GUI页面,但GUI比较慢,有些小的试验不妨先用console,当然在Qt里面可以直接使用cout, cin这些. 不过可能不会兼容Qt自带的一些类型,比如QByteArray等类型.在网上找了一下,发现可以用如下的方法来进行输出. 首先需要包含下列头文件: #include <QTextStream> #include <stdio.h> 然后,在使用cin.cout.cerr之前,创建下列变量: QTextStream cin(stdin,  QIODev

c++ cout&lt;&lt; cin&gt;&gt; 注释符 详解

std::cout是在#include<iostream>库中的ostream类型中的对象 std::表示命名空间,标准库定义的所有名字都在命名空间std中 std::cout是在#include<iostream>库中的istream类型中的对象 std::cout<<a<<std::endl; 上条语句中<<是输入运算符,就是将大头的那边的量弄进箭头所指的对象中,并返回运算之后的箭头所指的对象 std::endl是一个操纵符,作用是结束当前行

cin、cout

后缀名 C语言:C OC:m JS:js JAVA:java 先有类,再有函数 eclipse C++:cpp c plus plus 完全兼容C语言,以前叫c with classes(带有类的C语言) C++程序的入口是main函数(函数和方法一个意思和本质,汇编一模一样,随意叫) cin(从键盘接收).cout cin.cout控制台的输入,输出 依赖于上下文 #include <iostream> using namespace std; cout << "tes

C++中cin.clear()的用法

我们谈谈cin.clear的作用,第一次看到这东西,很多人以为就是清空cin里面的数据流,而实际上却与此相差很远,首先我们看看以下代码: #include <iostream>  using namespace std;  int main()   {              int a;              cin>>a;              cout<<cin.rdstate()<<endl;              if(cin.rds

cin对象的一些常用方法使用总结

>> 最初定义的是右移,当但是出现在 cin >>中的时候这个符号被重载了,变成了一个流操作,在用户通过键盘输入信息的时候,所有内容都会先直接存储在一个叫输入缓冲区的的地方,cin >> 就会直接像从输入缓冲区中直接读取按照你所提供的要求的类型的数据. cin.peek();  这个方法是取得输入流中的第一个字符进行其他操作如比较,但是不影响输入流中的数据. #include<iostream> using namespace std; int main()

C语言-cout&lt;&lt;"123"&lt;&lt;"45"&lt;&lt;endl;

VC中头文件为:#include <iostream.h> 这个在c中没有.是C++引进的. cout<头文件#include中printf()类似. 只是不需要标明数据类型. endl就是end of line的意思.honly:为避免ElemType的类型变化的影响,用cout取代printf().注意结尾要加endl.比如ElemTypede的类型发生变化,相应的printf()中的输出格式控制符必须进行相应的改变,否则会发生错误,因此用cout输出.1.\n与endl区别在于:

c++ cout介绍与实现自己的cout

C++编程语言互换流中的标准输出流,需要iostream支持.读为 "c out([si:‘a?t]". 名字 cout 类型 std::ostream 读为 "c out" 本相 std::cout.operator<<()函数 使用范例 听语音 #include<iostream> using namespace std; int main() { int a; cout << "请输入一个数字,按回车结束"

cin中函数的作用

cin是istream类的对象,它是从标准输入设备(键盘)获取数据,程序中的变量通过流提取符">>"从流中提取数据.流提取符">>"从流中提取数据时跳过输入流中的空格.tab键.换行符等空白字符.注意:只有在输入完数据再按回车键后,该行数据才被送入键盘缓存区,形成输入流,提取运算符">>"才能从中提取数据.需要注意保证从流中读取数据能正常运行.  例如: int a,b;        cin>>a

C++基础:各种输入方法总结,cin、cin.get()、cin.getline()、getline()、gets()

在C++中,各种输入方法还是不少的,而且各有所异,本文做一点简要总结,主要涉及如下内容:cin.cin.get().cin.getline().getline().gets().getchar(). 输入原理简述: 程序的输入都建有一个缓冲区,即输入缓冲区.每次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据.正因为cin函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入. 比如