def*_*nst 7 c++ iostream operator-overloading c++11
在ostream
类C++的提供了许多默认重载operator<<
,但他们不是以同样的方式定义的所有.
的重载为char
类型,string
类型和右值流被定义为自由namespace
-scope功能如:
namespace std {
ostream &operator<<(ostream &os, char c);
}
Run Code Online (Sandbox Code Playgroud)
虽然算术类型和流操作符的重载streambuf
被定义为成员函数,std::ostream
例如:
namespace std {
ostream &ostream::operator<<(int val);
}
Run Code Online (Sandbox Code Playgroud)
有这种区别的原因吗?我理解对这些运算符重载的调用操作稍有不同(即自由namespace
-scope定义的ADL ),因此我认为出于优化目的,可能会优先考虑特定类型的运算符重载.但是这里std::ostream
对不同类型使用两种类型的定义.这允许的语义或实现优化是否有任何优势?
我想,出于优化目的,可能会偏好特定类型的运算符重载
好吧,不.在一天结束时,两者都作为函数调用执行.重载决策本身甚至没有明显的含义.由于标准规定在[over.match],第2和第6段:
如果任一操作数具有类或枚举类型,则可以声明用户定义的操作符函数来实现此运算符,或者可能需要用户定义的转换将操作数转换为适合于构造函数的类型.在运营商.在这种情况下,重载决策用于确定调用哪个运算符函数或内置运算符来实现运算符.
重载决策的候选函数集是成员候选者,非成员候选者和内置候选者的联合.参数列表包含运算符的所有操作数.根据[over.match.viable]和[over.match.best]选择候选函数集中的最佳函数.
所有这些操作员重载都一起解决.唯一的语义差异是派生的类ostream
可以选择隐藏某些成员重载.这是根据派生类中的重载方式来完成的.只有明确声明的重载才适用.与那些成员不同,自由函数重载将始终参与重载解析,即使对于派生自的类也是如此ostream
.
由于派生类需要转换ostream&
为a以便选择自由函数重载,因此需要对其自己的隐式转换序列进行排序.如果所有重载都是自由函数,则可能会导致歧义.
因此,考虑很可能是将可能导致歧义(指针和算术类型)的类型与我们可能总是希望可用的有用类型(指向C字符串和单个字符的指针)分开.并允许隐藏"不太有用"的那些,以避免这些含糊不清.
正如WF指出的ostream
是,其实basic_ostream<char>
.自由函数恰好适用于仅需要流式传输的数据.流本地"字母"中的字符或字符串.所以对于basic_ostream<wchar_t>
那些免费的功能将接受wchar_t
和wchar_t*
.简单的流媒体很可能不需要访问流私有部分.
其他重载适用于在流式传输之前需要序列化的数据.由于所述序列化与流内部状态紧密耦合,因此使这些重载成为成员更有意义.