Chinaunix首页 | 论坛 | 博客
  • 博客访问: 117908
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 242
  • 用 户 组: 普通用户
  • 注册时间: 2014-07-17 13:36
文章分类

全部博文(29)

文章存档

2015年(29)

我的朋友

分类: C/C++

2015-04-17 08:26:00

C++cout的使用

coutc++中未ostream类型,也就是说,cout是要个类,但是ostream类型有点特别,因为它的构造函数是保护成员,也就是说,您不能够声明一个对象为ostream类型。但是,在std空间中提供了一个ostream全局变量cout供编程人员使用。那既然构造函数是保护成员,那怎么能产生示例呢?您可以去看看单例模式,那里会给您答案,因为本篇不是讲解设计模式,对于单例模式的解释暂且略过。

 

一、cout的使用

cout 相对于c中的printf,有它独特的地方,printf在输出内容时,如果内容的类型、个数不一定,需要在格式化字符串中指明类型,而cout就不需要,好像什么类型的数据给他,都会进行正确的解析,是不是很神奇。当然,这些神奇都是人为实现的,如果您定义了一个自己的类型,比如struct A吧,您认为cout神通广大,可以用cout输出A类型变量试试,一定会编译错误,很明显,cout不认识类型A,那如何让cout能够认识A呢?用一种在c++中特殊的技术,叫做运算符重载。

重载:函数或方法(其实是一个意思,通常类中的函数叫做方法,类中的变量也会叫做属性)有相同的名称,但是,参数列表不相同的情形,这种同名不同参的函数或方法之间,相互称为重载函数或方法。

重载特性:重载函数必须在同一命名空间中,你说我在空间A中定义了fun,又在B中定义了fun,它们参数不同,能否构成重载?NOc++编译器为了实现重载功能,会对函数名进行修饰,其实,最后的函数已经可以说被修饰的面目全非了,这个被修饰后得到的名称叫做函数签名(Function Signature,在程序中,函数名可以相同,但是函数签名一定不能相同,否则会出现重定义,而C语言中没有这种名字修饰的机制,所以C语言是不支持重载滴。

函数签名分为两部分,即函数名+参数列表,其中函数名部分相同,参数列表不同的两个函数才能成为重载函数,而函数名包括命名空间的名称,所以如果两个函数的命名空间都不同,那么可以说函数名部分就不相同了,根本无所谓重载,另外,还能解释为什么如果函数名相同、参数系统,但是返回值不同不能构成重载,因为函数签名中根本没有返回值,那在这种情况下,函数签名一定是相同的,所以提示重定义错误了。

那说了这么多,到底怎么对cout“<<”运算符进行重载呢?店小二,上代码:

struct A

{

    int m_value;

    char m_name[10];

};

 

ostream& operator<<(ostream& o,const A& a)

{

    return o << "A(" << a.m_value << ',' << a.m_name << ')';

}

这就是对运算符 << 的重载。调用代码如下:

A a = {12,"jame"};

cout << a << endl;

输出结果为:A(12,jame)

关于运算符的重载,下一篇在给各位看官慢慢说来。

 

二、cout的格式化输出

C语言中,在格式化字符串中,“%x”代表16进制输出,”%o”代表8进制输出,“%d”代表十进制输出,那cout中如何控制输出格式呢?

 

C++中,有一个标志类型ostream::fmtflags用于记录cout的当前格式。

大家如果在改变格式并完成一定的操作,想恢复原格式,可以先将该变量存下来,之后恢复。

如下:

ostream::fmtflags fs = cout.flags();   //获得原始flags

cout << oct;                    //设置以8进制输出

    cout << 13 << endl;

    cout << "------" << endl;

    cout.flags(fs);                        //恢复原始格式

    cout << 13 << endl;

当然”cout << oct”; 等价于”oct(cout)”;

为啥会这样呢?您可以用cout << typedef(oct).name() << endl;查看一下oct的类型,其中typedef中的类,成员函数name可以输出变量的类型信息,输出为“FRSt8ios_baseS0_E”(该结果为32windows cygwin下的输出结果,其他平台可能存在不同),第一个F代表oct为一个函数。

我的理解是,如果调用oct(cout)的形式改变coutflag,这是理所当然的,因为oct本来就是函数嘛,那为什么用运算符 << 也能达到相同的效果呢?应该是在cout的操作符 << 的重载函数中包含了动态类型转换dynamic_cast。以下内容为本人猜测:

octhexdec都为函数,他们的类型都为 void fun(ostream& o);那么定义一个这种函数的类型“typedef fun(ostream& o);”然后通过重载<<操作符,“ostream& operator<<(ostream&o, void*  input_fun)”,在函数体中,通过dynamic_cast(input_fun),返回为NULL,不是这种类型的函数,如果不为NULL,直接用dynam_cast的返回值作为函数,通过调用改变flags

当然,实际情况比这个复杂。

 

其他的格式如下:

调整字段宽度:cout.width(10);

恢复默认宽度:cout.width();

设置填充字符:cout.fill(‘0’);

设置浮点数显示精度:cout.precision(2);

恢复默认角度:cout.precision();

设置左对齐:cout.flag(ios::left);

设置右对齐:cout.flag(ios::right);

阅读(4277) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~