博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么可以用while(cin)?
阅读量:5925 次
发布时间:2019-06-19

本文共 3357 字,大约阅读时间需要 11 分钟。

 
/** *  @brief  The quick-and-easy status check. * *  This allows you to write constructs such as *  "if (!a_stream) ..." and "while (a_stream) ..."*/operator void*() const{ return this->fail() ? 0 : const_cast
(this); }

如果你把一个basic_ios类的对象(cin就是)放到if语句的括号里,它就会被转换成void*型。如果输入失败的话,就会得到一个空指针(也就是0),那么if语句就不能通过。

#include
#include
using namespace std;int main(){ int i; do   { cout<
<
>i);}

首先输出个0.之后输入X,输出X;当输入ctrl+d时,没有输出,结束。

#include
#include
using namespace std;int main(){ int i; do{ cin>>i; cout<
<

输入x,输出x;当输入ctrl+d时,再输出个上一次的输入量,结束。

ctrl+d表示表示输入错误。

cin.clear()可以重新将cin置为有效。

 

导致循环终止的原因是流对象cin进入错误状态:系统输入级故障;读入了无效数据;遇到文件结束符。

下面是一个用到cin判断作为循环条件的程序:

#include
#include
#include
#include
using namespace std;int main(){ map
< pair
> > family; pair
pa; string surName,childName,birthDate; do{ cout<<"enter surname"<
>surName; if(!cin) break;                     //如果cin无效,跳出循环 vector< pair
> child; pair
> >::iterator,bool> ret = family.insert(make_pair(surName,child)); cout<<"input name and age"<
>surName>>birthDate) { pair
pa; pa = make_pair(surName,birthDate); ret.first->second.push_back(pa);     //ctrl+d跳出循环,此时cin无效 } cin.clear();           //使cin重新有效,以达到下面while循环条件。 }while(cin); cout<<"enter search"<
>surName; map
< pair
> >::iterator it = family.find(surName); if(it==family.end()) cout<<"no this surname"<
>::iterator itt = it->second.begin(); while(itt!=it->second.end()) { cout<<(*itt).first<<"\t\t"<<(*itt).second<

 

 

今天看书的时候看到代码while(cin>>val),忽然就在想这样写的合法性是如何判定的。我们都知道cin是一个流对象,而>>运算符返回左边的流对象,也就是说cin>>val返回cin,于是while(cin>>val)就变成了while(cin),问题就变成了一个流对象在判断语句中的合法性。

       不管是while(cin)还是if(cin),都是合法的,为什么呢?我们自己定义一个类,然后定义该类的对象,然后使用if语句来判断它是不合法的。这说明,流对象具有某种转换函数,可以将一个流对象转换成判断语句可以识别的类型。

        打开iostream.h文件,找到cin的定义,发现是来自于istream.h,其中的模板类basic_istream继承自basic_ios,打开basic_ios的定义,发现它继承自ios_base,再次定位到ios_base类,发现它有两个重载函数。operator void *() const和bool operator!() const。这两个函数使得流对象可作为判断语句的内容。

        operator void *() const;函数在while(cin)或是if(cin)时被调用,将流对象转换成void *类型。

        bool operator!() const;函数在while(!cin)或是if(!cin)时被调用,将流对象转换成bool类型。

          C++中basic_ios.h中的函数定义如下:

 

[cpp] 
 
  1. /** 
  2.  *  @brief  The quick-and-easy status check. 
  3.  * 
  4.  *  This allows you to write constructs such as 
  5.  *  "if (!a_stream) ..." and "while (a_stream) ..." 
  6. */  
  7. operator void*() const  
  8. return this->fail() ? 0 : const_cast<basic_ios*>(this); }  
[cpp] 
 
  1. bool operator!() const  
  2. return this->fail(); }  

        因此,可以简单的理解调用过程为:

 

               while(cin)  =====> while(!cin.fail())              //while the stream is OK

               while(!cin) =====> while(cin.fail())               //while the stream is NOT OK

        需要指出的是,上述两个类型转换都是隐式的。

        既然我们找到了while(cin)合法的原因,自然需要试验一下。

        我们定义一个类A,在A中定义上述两个函数,然后定义A的一个对象a,使用if(a)和if(!a)来验证一下。代码如下:

 

[cpp] 
 
 
  1. #include<iostream>  
  2. using namespace std;  
  3. class A  
  4. {  
  5. public:  
  6.     A(){}  
  7.     ~A(){}  
  8.     operator void *()const  
  9.     {  
  10.         cout<<"cast to void*; ";  
  11.         return (void *)this;  
  12.     }  
  13.      bool operator!() const  
  14.     {  
  15.         cout<<"cast to bool; ";  
  16.         return true;  
  17.     }  
  18. };  
  19.   
  20. int main()  
  21. {  
  22.     A a;  
  23.     if(a) cout<<"first"<<endl;  
  24.     if(!a) cout<<"second"<<endl;  
  25.     return 0;  
  26. }  

        运行以上程序,结果为cast to void*; first和cast to bool; second。结果表明,if(a)隐式调用了operator void *()函数,if(!a)隐式调用了bool operator!()函数。

 

       上述两个函数其实是操作符的重载过程。使用这种重载函数,我们就可以像使用cin一样,用if语句对我们的对象做判断了。

转载地址:http://erxvx.baihongyu.com/

你可能感兴趣的文章
Extending A Linux Disk With LVM–Extending Root Par
查看>>
限制 HTTrack 直接 download 整個 website
查看>>
Quantum的GRE模式简介
查看>>
What Does SERIALIZABLE Really Mean?
查看>>
JAVA IO - File 常量属性
查看>>
Oracle创建悲观锁和乐观锁
查看>>
javascript 在 IE中出现 ERROR 尚未实现 错误
查看>>
WordPress 问题汇总
查看>>
Java 池技术 - commons-pool
查看>>
shell 删除指定文件名的日志
查看>>
查看ip地址来源(python脚本)
查看>>
UNIX各个系统比较和学习
查看>>
Common Lisp专题4:数组
查看>>
强行装载别人的页面
查看>>
开天辟地第一章
查看>>
dbdeploy的maven插件使用
查看>>
使用Apache htaccess加密保护文件
查看>>
勤于思考才能善于架构
查看>>
Linux wget
查看>>
压缩感知
查看>>