【问题标题】:Problem with chaining operator<< and operator++链接 operator<< 和 operator++ 的问题
【发布时间】:2020-01-12 12:05:07
【问题描述】:

我正在学习 C++,但遇到了这个问题:

#include <iostream>
using namespace std;


class test
{
    public:
    test(){};
    test(int i):var{i}{};

    test& operator++(){++var; return this;}  
    test  operator++(int dummy){test tmp =*this;var++;return tmp;}

    friend ostream& operator<<(ostream&, const test&);


   private:
   int var;
};

ostream& operator<<(ostream& o, const test& obj)
{
    o<<obj.var;
    return o;
}


int main()
{
    test obj{2};
    cout << obj << endl;
    obj++;
    cout << obj << endl;
    cout << obj <<' '<< ++obj<<endl;

    return 0;
}

我期望的输出是: 2 3 3 4

相反,我有: 2 3 4 4

如果我用 obj++ 替换最后一个增量 ++obj ,情况就更奇怪了: 2 3 4 3

好像流读反了,能帮帮我吗?

【问题讨论】:

    标签: c++ c++11 output operator-overloading increment


    【解决方案1】:

    让我们来看看这条线是怎样的

    cout << obj << ' ' << ++obj << endl;
    

    已翻译。

    第 1 步。

    cout << obj
    

    变成

    // A non-member function.
    operator<<(cout, obj)
    

    第 2 步。

    operator<<(cout, obj) << ' '
    

    变成

    // Also a non-member function.
    operator<<(operator<<(cout, obj), ' ')
    

    第 3 步。

    operator<<(operator<<(cout, obj), ' ') << ++obj
    

    变成

    // Also a non-member function.
    operator<<(operator<<(operator<<(cout, obj), ' '), ++obj)
    

    第 4 步。

    operator<<(operator<<(operator<<(cout, obj), ' '), ++obj) << endl;
    

    变成

    // A member function.
    operator<<(operator<<(operator<<(cout, obj), ' '), ++obj).operator<<(endl);
    

    这就是整行。

    在这样的表达式中,不能保证operator&lt;&lt;(cout, obj) 将在++obj 之前执行。似乎在您的平台中,++obj 在执行 operator&lt;&lt;(cout, obj) 之前执行。这解释了这种行为。

    请注意标准已更改。如果您能够使用 C++17,您将获得预期的行为。

    【讨论】:

    • 谢谢,我尝试使用 -std=c++17 进行编译,但输出保持不变。 gcc 编译器版本是 5.4.0,我不知道,但无论如何我有我的答案,我只是想弄清楚为什么。
    • 其实是operator&lt;&lt;(operator&lt;&lt;(operator&lt;&lt;(cout, obj).operator&lt;&lt;(' '), obj++), endl)
    • @0x499602D2,请查看更新后的答案。这和你的建议有点不同。请告知我的更新是否有任何错误。
    【解决方案2】:

    如果将使用默认构造函数,则数据成员 i 可以未初始化。

    要么像这样声明数据成员

    int var = 0;

    或者重新定义默认构造函数,例如使用委托构造函数。

    class test
    {
        public:
        test() : test( 0 ){};
        test(int i):var{i}{};
        // ...
    

    预增运算符应该是这样的

    test& operator++(){++var; return *this;}
                                     ^^^^^
    

    在后增量运算符中,不使用标识符dummy。所以删除它

    test  operator++( int ){test tmp =*this;var++;return tmp;}
    

    此声明

    cout << obj <<' '<< ++obj<<endl;
    

    具有未定义的行为,因为对象obj 的读写没有排序。

    你必须把这个语句分成两个语句

    cout << obj <<' ';
    cout << ++obj<<endl;
    

    【讨论】:

      猜你喜欢
      • 2020-04-13
      • 2012-01-03
      • 2013-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      相关资源
      最近更新 更多