Oracle Solaris Studio 12.2:C++ 用户指南

13.3.1 使用 iostream 进行输出

使用 iostream 进行的输出通常依赖于重载的左移运算符 (<<)(在 iostream 上下文中,称为插入运算符)。要将值输出到标准输出,应将值插入预定义的输出流 cout 中。例如,要将给定值 someValue 发送到标准输出,可以使用以下语句:


cout << someValue;

对于所有内置类型,都会重载插入运算符,且 someValue 表示的值转换为其适当的输出表示形式。例如,如果 someValuefloat<< 运算符会将该值转换为带小数点的适当数字序列。此处是将 float 值插入输出流中,因此 << 称为浮点插入器。通常,如果给定类型 X<< 称为 X 插入器。ios(3CC4) 手册页中讨论了输出格式以及如何控制输出格式。

iostream 库不支持用户定义的类型。如果要定义以自己的方式输出的类型,必须定义一个插入器(即,重载 << 运算符)来正确处理它们。

<< 可以多次应用。要将两个值插入 cout 中,可以使用类似于以下示例中的语句:


cout << someValue << anotherValue;

以上示例的输出在两个值间不显示空格。因此您可能会要按以下方式编写编码:


cout << someValue << " " << anotherValue;

运算符 << 优先作为左移运算符(其内置含义)使用。与其他运算符一样,总是可以使用圆括号来指定操作顺序。使用括号来避免优先级问题是个很好的方法。下列四个语句中,前两个是等价的,但后两个不是。


cout << a+b;              // + has higher precedence than <<
cout << (a+b);
cout << (a&y);            // << has precedence higher than &
cout << a&y;            // probably an error: (cout << a) & y

13.3.1.1 定义自己的插入运算符

以下示例定义了 string 类:


#include <stdlib.h>
#include <iostream.h>


class string {
private:
    char* data;
    size_t size;

public:
    // (functions not relevant here)

    friend ostream& operator<<(ostream&, const string&);
    friend istream& operator>>(istream&, string&);
};

在此示例中,必须将插入运算符和提取运算符定义为友元,因为 string 类的数据部分是 private


ostream& operator<< (ostream& ostr, const string& output)
{    return ostr << output.data;}

以下是为要用于 string 而重载的 operator<< 的定义。


cout << string1 << string2;

运算符 <<ostream&(也就是对 ostream 的引用)作为其第一个参数,并返回相同的 ostream,这样就可以在一个语句中合并多个插入。

13.3.1.2 处理输出错误

通常情况下,重载 operator<< 时不必检查错误,因为有 iostream 库传播错误。

出现错误时,所在的 iostream 会进入错误状态。iostream 状态中的各个位根据错误的一般类别进行设置。iostream 中定义的插入器不会尝试将数据插入处于错误状态的任何流,因此这种尝试不会更改 iostream 的状态。

通常,处理错误的推荐方法是定期检查某些中心位置中输出流的状态。如果有错误,就应该以某些方式来处理。本章假定您定义了函数 error,该函数可采用字符串并中止程序。error 不是预定义的函数。有关 error 函数的示例,请参见13.3.9 处理输入错误。可以使用运算符 ! 检查 iostream 的状态,如果 iostream 处于错误状态,该运算符会返回非零值。例如:


if (!cout) error("output error");

还有另外一种方法来测试错误。ios 类可定义 operator void *(),它在有错误时返回空指针。您可以使用如下语句:


if (cout << x) return; // return if successful

也可以使用函数 good,它是 ios 的成员:


if (cout.good()) return; // return if successful

错误位在 enum 中声明:


enum io_state {goodbit=0, eofbit=1, failbit=2,
badbit=4, hardfail=0x80};

有关错误函数的详细信息,请参见 iostream 手册页。

13.3.1.3 刷新

与大多数 I/O 库一样,iostream 通常会累积输出并将其发送到较大且效率通常较高的块中。如果要刷新缓冲区,只要插入特殊值 flush。例如:


cout << "This needs to get out immediately." << flush;
 

flush 是一种称为操纵符的对象示例,它是一个值,可以插入 iostream 中以起到一定作用,而不是使输出其值。它实际上是一个函数,采用 ostream&istream& 参数,在对其执行某些操作后返回其参数(请参见13.7 操纵符)。

13.3.1.4 二进制输出

要获得原始二进制形式的值输出,请使用以下示例所示的成员函数 write。该示例显示了原始二进制形式的 x 输出。


cout.write((char*)&x, sizeof(x));

以上示例将 &x 转换为 char*,这违反了类型规程。一般情况下,这样做无关大碍,但如果 x 的类型是具有指针、虚拟成员函数的类或是需要 nontrivial 构造函数操作的类,就无法正确读回以上示例写入的值。