涉及临时工的运算符重载决策的顺序

Tho*_*mas 11 c++ operator-overloading member-functions overload-resolution

请考虑以下最小示例:

#include <iostream>

using namespace std;

class myostream : public ostream {
    public:
        myostream(ostream const &other) :
            ostream(other.rdbuf())
        { }
};

int main() {
    cout << "hello world" << endl;

    myostream s(cout);
    s << "hello world" << endl;

    myostream(cout) << "hello world" << endl;
}
Run Code Online (Sandbox Code Playgroud)

g ++和Visual C++上的输出都是

hello world
hello world
0x4012a4
Run Code Online (Sandbox Code Playgroud)

写入临时对象的版本myostream(cout)似乎更喜欢成员运算符ostream::operator<<(void *),而不是自由运算符operator<<(ostream &, char *).对象是否有名称似乎有所不同.

为什么会这样?我该如何防止这种行为?

编辑:为什么它发生现在从各种答案清楚.至于如何防止这种情况,以下似乎很吸引人:

class myostream : public ostream {
    public:
        // ...
        myostream &operator<<(char const *str) {
            std::operator<<(*this, str);
            return *this;
        }
};
Run Code Online (Sandbox Code Playgroud)

然而,这导致各种模糊.

小智 7

如果对象没有名称(即它是临时的),则不能绑定到非const引用.具体来说,它不能绑定到第一个参数:

operator<<(ostream &, char *)
Run Code Online (Sandbox Code Playgroud)


APr*_*mer 6

rvalues不能绑定到非const引用.所以在你的例子中,类型ostream的临时类不能是自由运算符<<(std :: ostream&,char const*)的第一个参数,使用的是成员运算符<<(void*).

如果需要,可以添加如下调用

myostream(cout).flush() << "foo";
Run Code Online (Sandbox Code Playgroud)

这会将rvalue转换为参考.

请注意,在C++ 0X中,引入rvalue引用将允许提供操作符<<的重载,将rvalue引用作为参数,解决问题的根本原因.