运算符<<的全局重载不起作用,为什么?

Rah*_*hul 1 c++ operator-overloading

我知道operator <<可以通过使其成为类的朋友功能而重载。例如,

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;
}
Run Code Online (Sandbox Code Playgroud)
one
two
Run Code Online (Sandbox Code Playgroud)

这似乎按预期工作。

但是,我无法理解为什么同样的方法对于全局过载不起作用。

#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";
}
Run Code Online (Sandbox Code Playgroud)

stackoverflowstackoverflow

期望这些字符串用换行符分隔,但是没有按预期运行。

Vla*_*cow 6

您的运营商使用

std::cout << "stackoverflow";
Run Code Online (Sandbox Code Playgroud)

需要从类型的对象const char *(在将字符串文字隐式转换为指向第一个字符的指针的隐式转换之后)到类型的对象的用户定义转换std::string

但是,标准basic_ostream类已经具有不需要这种转换的运算符

template<class charT, class traits>
basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const char*);
Run Code Online (Sandbox Code Playgroud)

因此,将调用此运算符而不是您的运算符。

而且在您的操作员内

std::ostream & operator<<(std::ostream & os, const std::string & s)
{
    os << s << '\n';
    return os;
}
Run Code Online (Sandbox Code Playgroud)

本身有递归调用。

您可以通过以下方式定义您的操作员

#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";
}
Run Code Online (Sandbox Code Playgroud)

得到预期的结果

stackoverflow
stackoverflow
Run Code Online (Sandbox Code Playgroud)