为什么我的绳子打印在错误的地方?

时间:2019-05-21 21:44:07

标签: c++ output operator-overloading

我期望此输出:

  

加法:5/6/92 + 5/6/92 = 10/12/184

但我得到以下输出:

  

5/6/92 + 5/6/92 =添加:10/12/184

为什么会这样?

如何在不修改主要功能的情况下解决此问题?

#include <iostream>

using namespace std;

class Date {
    int mo, da, yr;
    public:
        Date(int m, int d, int y) {
            mo = m;
            da = d;
            yr = y;
        }
    friend ostream & operator << (ostream & os,
        const Date & dt);
    Date operator + (const Date & dat) const {
        Date newDate(0, 0, 0);
        newDate.mo = dat.mo + mo;
        newDate.da = dat.da + da;
        newDate.yr = dat.yr + yr;
        cout << dat << "+" << mo << "/" << da << "/" << yr << "=";
        return newDate;
    }
};

ostream & operator << (ostream & os,
    const Date & dt) {
    os << dt.mo << '/' << dt.da << '/' << dt.yr;
    return os;
}

int main() {
    Date dt(5, 6, 92);
    cout << "Addition: " << dt + dt;
}

2 个答案:

答案 0 :(得分:1)

问题是在执行dt + dt之前正在评估cout << "Addition: "

std::ostream没有使用operator<<const char[]作为输入的1参数成员Date方法,因此必须调用2参数非成员operator<<会超载。因此,语句cout << "Addition: " << dt + dt;最终看起来更像编译器:

operator<<(operator<<(cout, "Addition: "), dt + dt);

在外部operator<<调用中,编译器选择在评估第一个参数(dt + dt)之前评估第二个参数(operator<<(cout, "Addition: "))。

如果不修改main()来更改求值顺序以强制您想要的顺序,您就无法真正获得所需的结果,例如:

#include <iostream>
using namespace std;

class Date {
    int mo, da, yr;

    public:
        Date(int m, int d, int y) {
            mo = m;
            da = d;
            yr = y;
        }

    friend ostream & operator << (ostream & os, const Date & dt) {
        os << dt.mo << '/' << dt.da << '/' << dt.yr;
        return os;
        }

    Date operator + (const Date & dat) const {
        Date newDate(dat.mo + mo, dat.da + da, dat.yr + yr);
        cout << *this << "+" << dat << "=";
        return newDate;
    }
};

int main() {
    Date dt(5, 6, 92);
    cout << "Addition: ";
    cout << dt + dt;
}

不过,通常最好将operator+上的输出打印全部删除,只要让main()打印就可以了:

#include <iostream>
using namespace std;

class Date {
    int mo, da, yr;

    public:
        Date(int m, int d, int y) {
            mo = m;
            da = d;
            yr = y;
        }

    friend ostream & operator << (ostream & os, const Date & dt) {
        os << dt.mo << '/' << dt.da << '/' << dt.yr;
        return os;
        }

    Date operator + (const Date & dat) const {
        return Date(dat.mo + mo, dat.da + da, dat.yr + yr);
    }
};

int main() {
    Date dt(5, 6, 92);
    Date sum = dt + dt;
    cout << "Addition: " << dt << "+" << dt << "=" << sum;
}

答案 1 :(得分:0)

让我们看看cout << "Addition: " << dt + dt;

正在发生的事情是,dt + dt首先被评估,评估中包含cout。之后,程序将打印"Addition: ",最后打印先前评估的结果。

您在这里看到问题了吗?它不是像人类那样从左到右读取,并且不会在看到+运算符时进行评估。它会评估需要处理的所有内容(并调用cout内部的+),然后在获得所有答案后从左到右打印。

在操作符中包含打印语句通常不是一个好主意,可能只是为了调试。您应该将其删除。就您而言,只需简单地打印您想要的内容,然后打印结果即可。如果您愿意,甚至可以创建一个函数,该函数(1)打印有关该操作的信息,而操作数(2)调用该运算符(3)打印结果。例如:

// Don't forget to remove cout statements from the overloaded +
void printThenAdd(Date dt0, Date dt1) {
    cout << "Addition: ";
    cout << dt0.mo << '/' << dt0.da << '/' << dt0.yr << " + ";
    cout << dt1.mo << '/' << dt1.da << '/' << dt1.yr;
    cout << " = " << dt0 + dt1 << endl;
}

祝你好运!我可以看到这会令人困惑。