关于ostream类和运算符的误解<<

时间:2013-04-15 12:22:41

标签: c++ iostream

查看ostream::operator << c ++参考后,

我注意到以下声明:

ostream& operator<< (bool val);
ostream& operator<< (short val);
ostream& operator<< (unsigned short val);
ostream& operator<< (int val);
ostream& operator<< (unsigned int val);
ostream& operator<< (long val);
ostream& operator<< (unsigned long val);
ostream& operator<< (float val);
ostream& operator<< (double val);
ostream& operator<< (long double val);
ostream& operator<< (void* val);
ostream& operator<< (streambuf* sb );
ostream& operator<< (ostream& (*pf)(ostream&));
ostream& operator<< (ios& (*pf)(ios&));
ostream& operator<< (ios_base& (*pf)(ios_base&));

但后来我发现还有以下声明:

ostream& operator<< (ostream& os, char c);
ostream& operator<< (ostream& os, signed char c);
ostream& operator<< (ostream& os, unsigned char c);
ostream& operator<< (ostream& os, const char* s);
ostream& operator<< (ostream& os, const signed char* s);
ostream& operator<< (ostream& os, const unsigned char* s);

为什么char / string输出运算符不是成员函数?

5 个答案:

答案 0 :(得分:5)

第一组运算符是流类的成员。

大多数操作符重载(如第二组中的操作符重载)不是。


至于为什么,这可能只是一次历史性事故。内置类型的运算符可以添加到流类中,显然它们是(在C ++标准化之前很久)。该标准只记录了现有的做法。

用户定义类型的运算符显然无法添加到流类中,因此它们实现为自由函数。

回想起来,让所有运营商免费使用功能会更加一致,但这可能会破坏一些旧程序。

答案 1 :(得分:2)

其他人已经描述了这些差异,这是我为什么会分裂的原因。

char变量作为参数的非成员版本是专门的,具体取决于目标流的基本字符类型的类型,并根据区域设置进行处理,因为标准定义了特定的行为(o << '1'有不同的行为超过oo << 33,如果obasic_ostream<wchar_t>等,则必须妥善处理。

E.g。写入char的{​​{1}}被扩大,而如果写入basic_ostream<wchar_t>则不是(basic_ostream<char>。(27.6.2.5.4)。实际上有operator<<的多个重载,例如:

basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, char _Ch)
basic_ostream<char, _Traits>& <<(basic_ostream<char, _Traits>& _Ostr, char _Ch)

如果它们被定义为成员函数,那么你将不能像它那样专门化它们,因为你必须部分地专门化整个类,而不仅仅是单个成员,因为标准不允许对成员函数进行部分特化

答案 2 :(得分:1)

实际上有两个overloader operator<<系列,正如您所发现的那样。

一个系列是重载成员ostream::operator<<(隐式获取ostream引用作为this指针)而另一个系列是重载的自由函数operator<< ostream引用显式为参数。

如果要将流功能添加到自己的类中,可以添加自由功能。

答案 3 :(得分:0)

运营商的原因&lt;&lt;取char不是成员函数是因为ostream中已经定义了将字符写入流的函数。

basic_ostream& put(Ch c);
basic_ostream& write(const Ch* p, streamsize n);

因此,这些运算符成为非成员函数,在内部使用这两个函数。

答案 4 :(得分:-1)

第一个系列是成员函数,return *this因此操作符链可以工作。

第二个系列是独立功能(正如您所说,您可以为任何类添加,因此您可以将它们流式传输到std::ostream),这些功能没有this可以返回return os而是让操作员链接工作。

请注意,两者在呼叫站点的工作方式相同。