哪个<<在这个声明中是我的重载运算符?

时间:2012-01-16 17:05:30

标签: c++

我有一个重载<<我的reckful类的运算符实现如下:

ostream& operator << (ostream& os, const reckful& p)
{
    os << p.PrintStuff();

    return os;
}

PrintStuff()只是reckful的成员函数,返回一个字符串。

我理解事物的方式,如果我在main()中写cout << reckobject << endl;之类的东西,cout << reckobject将优先,我的重载&lt;&lt; (使用cout作为左操作数,reckobject作为右操作数)将返回ostream对象os,留下要评估的表达式os << endl;,它将输出字符串然后结束该行。所以,第一个&lt;&lt;是我宣布的那个,第二个是标准&lt;&lt;正确?

然而,我的主要问题是......事件的顺序是什么,它是左右操作数,以及&lt;&lt;当我运行这样的语句时,运算符就是这样的:

cout << "reckful object = " << reckobject << "!" << endl;

如果没有一个ostream对象和一个&lt;&lt;&lt;&lt;&lt;&lt; ?

感谢。

2 个答案:

答案 0 :(得分:5)

如果你注意到实现<<的标准方法,它会返回ostream本身。这是关键部分

类似

 cout << "reckful object = " << reckobject << "!" << endl;

将调用

一次

cout << "reckful object = " 

此函数调用将返回ostream,用于进行第二次调用

   cout  << reckobject;
等等等等。

您可以通过实施<<

来测试
void operator << (ostream& os, const reckful& p)
{  
    os << 1;
}

在这种情况下你可以做到

std::cout << p;

但不是

std::cout << p << std::endl;

运算符使其更难理解,但请考虑此Point

struct Point
{
    Point& setX( int x) { X = x; return *this;}
    Point& setY( int y) { Y = y; return *this;}

    int X;
    int Y;
};

setXsetY的定义方式允许

    Point p;
    p.setX( 2 ).setY( 4 );

这与<<用于链接函数调用的机制相同。

答案 1 :(得分:3)

因为每个<<都会返回对cout的引用。因为运算符<<是左关联的,所以调用是从左到右完成的,所以

a << b << c

相当于

(a << b) << c

等于 1

operator<<(operator<<(a, b), c);

所以在你的例子中,你正在做

operator<<(operator<<(operator<<(operator<<(cout, "reckful object = "), reckobject), "!"), endl);

正如您所看到的,每个<<取决于之前<<的返回值(如果没有进一步左cout,则仅<<)。如果您将<<的某个返回类型更改为void,则会有效停止<<次调用,因为void不能用作参数一个功能。


1 它并不完全等价,因为在那个例子中,所有operator<<都是自由函数,而实际上,有些可以是成员函数,所以你可以混合使用成员和非成员函数 - 成员呼叫

operator<<(a, b).operator<<(c);

operator<<(a.operator<<(b), c);