为什么运算符<<不适用于操作员返回的内容-?

发布于 2024-09-03 00:00:31 字数 7921 浏览 4 评论 0 原文

这是我编写的一个小测试程序:

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

我似乎不明白为什么标记为“这有效”的行有效,而标记为“这无效”的行则无效。当我尝试使用 cout<<(ba); 行编译程序时,我得到的结果如下:

[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]$

相当令人讨厌。

Here's a small test program I wrote:

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

I can't seem to get why the line marked "this works" works and the one marked "this doesn't" doesn't. When I try to compile the program with the cout<<(b-a); line, here's what I get:

[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]$

Quite nasty.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

猛虎独行 2024-09-10 00:00:31

你的operator+返回一个临时对象——在C++中你不能将临时对象绑定到非常量引用。您想要:

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

这是编写 opertaor<< 的规范方式对于流式传输 - 输出的内容应始终作为 const 引用传递。

Your operator+ returns a temporary object - and in C++ you can't bind temporaries to non-const references. You want:

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

This is the canonical way to write opertaor<< for streaming - the thing being output should always be passed as a const reference.

屋檐 2024-09-10 00:00:31

因为您不允许将临时变量传递给插入运算符。将其更改为:

friend ostream& operator<<(ostream &, const A &);
...
ostream& operator<<(ostream &out, const A &a) {
    out<<a.val;
    return out;
}

Because you are not allowing temporaries to be passed to your insertion operator. Change it to:

friend ostream& operator<<(ostream &, const A &);
...
ostream& operator<<(ostream &out, const A &a) {
    out<<a.val;
    return out;
}
漫雪独思 2024-09-10 00:00:31

在第二行中,您要求编译器从 A 转换为 A&,但 A 是临时的,这是非标准行为。在第一行中, c 不是临时的,因此它可以工作。
将运算符更改为

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

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

in the second line,you're asking the compiler to convert from A to A&, but A is a temporary, and that is non-standard behaviour. In the first line c is not temporary so it works.
Changing your operator to

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

will not only be more correct, but should also be accepted by the compiler.

聊慰 2024-09-10 00:00:31

临时对象基本上被视为 const,因此对于绑定到它的引用,它必须是对 const 的引用:

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

A temporary object is basically considered const, so for a reference to bind to it, it has to be a reference to const:

ostream& operator<<(ostream &out, A const &a) // ...
谎言月老 2024-09-10 00:00:31

您将一个临时对象传递给 operator<<,因此它需要采用 const A&

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

其他一些注意事项:

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

最好将单参数构造函数标记为显式,这样可以防止您到处创建意外的临时对象,从而降低性能。

explicit A(int _val=0):val(_val) { }

You're passing a temporary object to operator<<, so it needs to take a const A&.

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

A few other notes:

Always use 'const T&' when passing non-primitive arguments that are not modified. This allows you to pass temporaries, and indicates that you don't change the parameter.

It's best to mark single argument constructors explicit, this prevents you from making accidental temporary objects everywhere, killing your performance.

explicit A(int _val=0):val(_val) { }
瑕疵 2024-09-10 00:00:31

std::basic_ostream::operator<< 在您的用例中需要 const 限定的参数。因此,您需要按如下方式更正操作员的签名:

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

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

The std::basic_ostream::operator<< expects const-qualified argument in your use case. Thus, you need to correct the signature of your operator as follows:

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

By the way, the friendship is redundant because A::val is public, thus accessible anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文