10

在查看了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);

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

4

5 回答 5

6

第一组操作符是流类的成员。

大多数运算符重载,如第二组中的那些,都不是。


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

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

回想起来,让所有运算符都成为自由函数会更加一致,但这可能会破坏一些旧程序。

于 2013-04-15T12:29:11.580 回答
2

其他人已经描述了差异,这是我对他们分裂的原因的看法。

将变体作为参数的非成员版本char根据目标流的基本字符类型的类型进行专门化,并根据语言环境进行处理,因为标准定义了特定的行为(o << '1'与 具有不同的行为oo << 33,如果ois 则必须正确处理basic_ostream<wchar_t>,等等)。

例如, charwriten tobasic_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)

如果它们被定义为成员函数,您将无法像那样专门化它们,因为您必须部分专门化整个类,而不仅仅是单个成员,因为标准不允许成员函数的部分专门化。

于 2013-04-15T12:57:28.060 回答
1

operator<<正如您所发现的,实际上有两个过载者家族。

一个族是重载成员(隐式ostream::operator<<获取引用作为指针),另一个族是重载自由函数,它显式获取引用作为参数。ostreamthisoperator<<ostream

当您想为自己的类添加流式传输功能时,您可以添加一个免费功能。

于 2013-04-15T12:30:52.043 回答
0

operator<< 采用 char 不是成员函数的原因是 ostream 中已经定义了将字符写入流的函数。

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

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

于 2014-11-23T09:27:56.563 回答
-1

第一个系列是成员函数,return *this因此运算符链接有效。

第二个系列是独立函数(正如您所说,您可以为任何类添加它,以便您可以将它们流式传输到 a std::ostream),它没有this返回,return os而是使运算符链接工作。

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

于 2013-04-15T12:29:12.523 回答