代码之家  ›  专栏  ›  技术社区  ›  Felix

为什么operator<<不处理operator返回的内容?

  •  1
  • Felix  · 技术社区  · 15 年前

    我写了一个小测试程序:

    #include <iostream>
    using namespace std;
    
    class A {
    
        public:
        int val;
    
        A(int _val=0):val(_val) { }
    
        A operator+(A &a) { return A(val + a.val); }
        A operator-(A &a) { return A(val - a.val); }
    
        friend ostream& operator<<(ostream &, A &);
    
    };
    
    ostream& operator<<(ostream &out, A &a) {
        out<<a.val;
        return out;
    }
    
    int main() {
        A a(3), b(4), c = b - a;
        cout<<c<<endl; // this works
        cout<<(b-a)<<endl; // this doesn't
        return 0;
    }
    

    我似乎不明白为什么标记为“this works”的行有效,而标记为“this not”的行无效。 cout<<(b-a); 行,我得到的是:

    [felix@the-machine C]$ g++ test.cpp 
    
    test.cpp: In function ‘int main()’:
    test.cpp:26:13: error: no match for ‘operator<<’ in ‘std::cout << b.A::operator-(((A&)(& a)))’
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:108:7: note: candidates are: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:117:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ios_type& (*)(std::basic_ostream<_CharT, _Traits>::__ios_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>, std::basic_ostream<_CharT, _Traits>::__ios_type = std::basic_ios<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:127:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:165:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:169:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:173:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/ostream.tcc:91:5: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:180:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/ostream.tcc:105:5: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:191:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:200:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:204:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:209:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:213:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:221:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:225:7: note:                 std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
    /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/ostream.tcc:119:5: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__streambuf_type*) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__streambuf_type = std::basic_streambuf<char>]
    test.cpp:18:11: note:                 std::ostream& operator<<(std::ostream&, A&)
    [felix@the-machine C]$
    

    非常讨厌。

    6 回复  |  直到 15 年前
        1
  •  10
  •   anon    15 年前

    您的运算符+返回一个临时对象-在C++中,您不能将临时绑定到非const引用。你想要:

    ostream& operator<<(ostream &out, const A &a) {
    

    这是编写用于流式处理的操作工<<的标准方法-输出的内容应始终作为常量引用传递。

        2
  •  3
  •   Khaled Alshaya    15 年前

    因为您不允许将临时文件传递给插入运算符。把它改成:

    friend ostream& operator<<(ostream &, const A &);
    ...
    ostream& operator<<(ostream &out, const A &a) {
        out<<a.val;
        return out;
    }
    
        3
  •  3
  •   stijn    15 年前

    在第二行中,您要求编译器从A转换为A&,但A是临时的,这是非标准行为。在第一行,C不是临时的,所以它起作用。 将操作员更改为

    ostream& operator<<(ostream &out, const A &a)
    

    不仅会更正确,而且应该被编译器接受。

        4
  •  1
  •   Jerry Coffin    15 年前

    基本上考虑临时对象 const ,因此,对于要绑定到它的引用,它必须是对const的引用:

    ostream& operator<<(ostream &out, A const &a) // ...
    
        5
  •  1
  •   Stephen    15 年前

    你将一个临时对象传递给 operator<< ,所以需要 const A& .

    std::ostream& operator<<(std::ostream&, const A&)
    

    其他几点注意事项:

    传递未修改的非基元参数时,始终使用“const&”。这允许您传递临时变量,并指示您不更改参数。

    最好标记单参数构造函数 explicit ,这可以防止您在任何地方制造意外的临时对象,从而破坏您的性能。

    explicit A(int _val=0):val(_val) { }
    
        6
  •  0
  •   mloskot    15 年前

    这个 std::basic_ostream::operator<< 在用例中需要常量限定的参数。因此,您需要如下更正操作员的签名:

    ostream& operator<<(ostream &out, A const& a)
    

    顺便说一下,友谊是多余的,因为 A::val 是公共的,因此无论如何都可以访问。