查看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输出运算符不是成员函数?
答案 0 :(得分:5)
第一组运算符是流类的成员。
大多数操作符重载(如第二组中的操作符重载)不是。
至于为什么,这可能只是一次历史性事故。内置类型的运算符可以添加到流类中,显然它们是(在C ++标准化之前很久)。该标准只记录了现有的做法。
用户定义类型的运算符显然无法添加到流类中,因此它们实现为自由函数。
回想起来,让所有运营商免费使用功能会更加一致,但这可能会破坏一些旧程序。
答案 1 :(得分:2)
其他人已经描述了这些差异,这是我为什么会分裂的原因。
以char
变量作为参数的非成员版本是专门的,具体取决于目标流的基本字符类型的类型,并根据区域设置进行处理,因为标准定义了特定的行为(o << '1'
有不同的行为超过oo << 33
,如果o
为basic_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
而是让操作员链接工作。
请注意,两者在呼叫站点的工作方式相同。