Overloading postfix operator doesn't work

2019-09-06 11:41发布

问题:

#include <iostream>

using namespace std;

class NumDays
{
private:
    int hour;
    int day;
    void simplify();

public:
    NumDays()
    {
        day = 0;
        hour = 0;
    }

    void setData(int d, int h)
    {
        hour = h;
        day = d;
        simplify();
    }

    int getHour()
    {
        return hour;
    }

    int getDay()
    {
    return day;
    }

    NumDays operator++(int);
    NumDays operator--(int);

};

void NumDays::simplify()
{
    hour = 8*day + hour;
    day = hour / 8;
    hour = hour % 8;
}

NumDays NumDays::operator++(int)
{
    NumDays obj1;

    hour++;
    simplify();
    return obj1;
    }

NumDays NumDays::operator--(int)
{
    NumDays obj1;

    hour--;
    simplify();
    return obj1;
}

void setFirst(NumDays &);
void setSecond(NumDays &);

void addData(NumDays &, NumDays &, NumDays &);

int main()
{
    NumDays first, second, third;

    setFirst(first);
    setSecond(second);

    addData(first, second, third);
}

void setFirst(NumDays &obj1)
{
    int day, hour = 0;
    cout << "Please enter the amount of days followed by hours." << endl;
    cin >> day >> hour;
    obj1.setData(day, hour);
}

void setSecond(NumDays &obj2)
{
    int day, hour = 0;
    cout << "Please enter the amount of days followed by hours again." << endl;
    cin >> day >> hour;
    obj2.setData(day, hour);
}

void addData(NumDays &obj1, NumDays &obj2, NumDays &obj3)
{
    for (int k = 0; k < 8; k++)
    {
    obj3 = obj1++;
    cout << "  First Data: " << obj3.getDay() << " day(s), "
         << obj3.getHour() << " hour(s).";
    cout << "  First Data: " << obj1.getDay() << " day(s), "
         << obj1.getHour() << " hour(s).\n";
    }

    cout << endl;

    for (int l = 0; l < 8; l++)
    {
    obj3 = obj2++;
    cout << "   Second Data: " << obj3.getDay() << " day(s), "
         << obj3.getHour() << " hour(s).";
    cout << "   Second Data: " << obj2.getDay() << " day(s), "
         << obj2.getHour() << " hour(s).\n";
    }
}

When I run the file, the obj3 have 0 days and 0 hours and the obj2 increases. How come it is like this? When I tried it as obj3 = obj2 without any postfix signs, it copies it over. So that I assume that there is no problem on getting data from obj2. But when I include the postfix operator, the data becomes 0 and 0.

回答1:

You've got it almost right. First, I made a few changes to your class.

class NumDays
{
private:
    int hour;
    int day;
    void simplify();

public:
    NumDays(int dy = 0, int hr = 0) : hour(hr), day(dy) { simplify(); }
    void setData(int d, int h)
    {
        hour = h;
        day = d;
        simplify();
    }
    int getHour() const { return hour; }
    int getDay() const { return day; }
    friend ostream& operator<<(ostream& out, const NumDays &nd) {
    return out << "  First Data: " << nd.getDay() << " day(s), "
         << nd.getHour() << " hour(s).";
    }
    NumDays operator++(int);
};

The first thing I did was to rewrite the constructor to have default arguments and to use a modern style.

The second thing I did was to add const to various member functions that don't (and shouldn't) modify the object.

The third thing I did was to add an ostream extractor as a friend function. This was purely for convenience to troubleshoot the problem.

Here's what the new version of the postincrement operator looks like:

NumDays NumDays::operator++(int)
{
    NumDays obj1(*this);
    hour++;
    simplify();
    return obj1;
}

The only difference is that the creation of obj1 now uses the default compiler-generated copy constructor. This is important because we need to return a copy of the unincremented value for a postincrement operator. (Your postfix decrement operator needs a similar fix.)

I made no changes to your simplify() routine.

I then tested it with this code:

int main()
{
    NumDays nd(2,3);
    cout << nd++ << endl;   // prints 2, 3
    cout << nd << endl;     // prints 2, 4
    return 0;
}

And now everything works.



回答2:

When you modify hour inside of operator++() you are change the value of this->hour. The content of obj1 which is completely independent of *this is not changed. You want to get rid of obj1.

I'm not sure what you want to return here... if you return the "simplified" value of hour it will be very unintuitive because we expect ++ to return a value 1 greater than it started with. It's a violation of the Principle of Least Astonishment. :)

So you really should create a new function and not override operator++. Or, if you override operator++, then don't call simplify() inside of it.