簡體   English   中英

operator<< 的全局重載不起作用,為什么?

[英]Global overload of operator<< does not work, why?

我了解到operator<<可以通過使其成為 class 的朋友 function 來重載。 例如,

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

期望字符串用換行符分隔,但沒有按預期工作。

您的運營商使用

std::cout << "stackoverflow";

需要從const char *類型的 object (在將字符串文字隱式轉換為指向其第一個字符的指針之后)到std::string類型的 object 的用戶定義轉換。

然而,標准 basic_ostream class 已經有一個不需要這種轉換的運算符

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

請注意, "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 );

順便說一句:因為ADL可以找到它。

您可以全局重載,但"stackoverflow"不是std::string ,因此不使用您的。
(而且標准庫中已經存在這樣的重載。)

要查看它是否有效,請將您的第一個重載移出 class 定義並使其成為非朋友。
必須將其聲明為friend的唯一原因是您已在 class 定義中聲明它,否則它將是成員 function 。

這將按您的預期工作:

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM