我了解到 operator <<< / em> 可以通过使其成为类的好友函数而重载。 例如,
struct Test
{
std::string d_data;
Test(const std::string & data) : d_data{data} {}
friend std::ostream & operator<<(std::ostream & ostr, const Test & obj)
{
ostr << obj.d_data << '\n';
return ostr;
}
};
int main()
{
Test t1("one");
std::cout << t1;
Test t2("two");
std::cout << t2;
}
one two
这似乎按预期工作。
但是,我无法理解为什么同样的方法对于全局重载不起作用。
#include <iostream>
#include <ostream>
#include <string>
std::ostream & operator<<(std::ostream & os, const std::string & s)
{
os << s << '\n';
return os;
}
int main()
{
std::cout << "stackoverflow";
std::cout << "stackoverflow";
}
stackoverflowstackoverflow
期望这些字符串要用换行符分隔,但不能按预期工作。
答案 0 :(得分:6)
您的运算符使用
std::cout << "stackoverflow";
需要用户定义的转换,类型为const char *
的对象(在将字符串文字隐式转换为指向其第一个字符的指针之后)到类型为std::string
的对象。
但是标准basic_ostream类已经具有不需要这种转换的运算符
template<class charT, class traits>
basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const char*);
因此将调用此运算符而不是您的运算符。
此外,您的运营商之内
std::ostream & operator<<(std::ostream & os, const std::string & s)
{
os << s << '\n';
return os;
}
本身存在递归调用。
您可以通过以下方式定义您的运营商
#include <iostream>
#include <string>
std::ostream & operator<<(std::ostream & os, const char *s)
{
return std::operator <<( os, s ) << '\n';
}
int main()
{
std::cout << "stackoverflow";
std::cout << "stackoverflow";
}
并获得预期的结果
stackoverflow
stackoverflow
答案 1 :(得分:4)
请注意,"stackoverflow"
的类型为const char[]
,而不是std::string
。这意味着将不会调用您的重载,而是会调用标准库中的重载(operator<<(std::basic_ostream)
,因为它是完全匹配的,不需要从const char[]
到std::string
的隐式转换
template< class Traits > basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os, const char* s );
BTW:可能是由于ADL导致的。
答案 2 :(得分:1)
您可以全局重载,但是"stackoverflow"
不是std::string
,因此不会使用您的。
(而且标准库中已经有这样的重载。)
要查看其效果,请将您的第一个重载移出类定义,并使其成为非好友。
必须将其声明为friend
的唯一原因是您已在类定义中声明了它,否则它将成为成员函数。
这将按预期工作:
struct Test
{
std::string d_data;
Test(const std::string & data) : d_data{data} {}
};
std::ostream & operator<<(std::ostream & ostr, const Test & obj)
{
ostr << obj.d_data << '\n';
return ostr;
}
int main()
{
Test t1("one");
std::cout << t1;
Test t2("two");
std::cout << t2;
}