我的重载后增量方法不能按预期工作。为什么呢?

时间:2018-02-09 05:45:47

标签: c++ c++11 overloading post-increment

我有这个C ++类,它接受一年中的一天数并将其转换为月 - 日格式。它工作正常,但我的问题是我的重载后增量运算符不能按预期工作。

我理解以下代码......

int x = 10;
std::cout << "x: " << x << "\n";
std::cout << "x++: " << x++ << "\n"; // Gives x, then increments.
std::cout << "++x: " << ++x << "\n\n"; // Increments, then gives x.

...打印以下内容:

x: 10
x++: 10
++x: 12

因此,后增量首先将对象传递给&lt;&lt;然后递增它。虽然预增量将一个添加到对象,然后将其传递给&lt;&lt;。

但是,在下面的代码中,重载的后增量方法与预增量方法的作用相同 - 正如我所理解的那样,不应该发生。这里发生了什么?

三个文件:(1)main.cpp(2)DayOfYearMod.h,(3)DayOfYearMod.cpp

的main.cpp

#include <iostream>
#include "DayOfYearMod.h"

int main() {
    DayOfYearMod in(1); // Day 1 for January 1.

    std::cout << "Test 1. Inline: \n";
    std::cout << " ... in: " << in << "\n";
    // Next. Supposed to pass Jan. 1 to << but passed Jan. 2
    std::cout << " ... in++: " << in++ << "\n";
    std::cout << " ... in: " << in << "\n";
    // Next. Pass Jan. 2 + 1 to <<. Works as expected.
    std::cout << " ... ++in: " << ++in << "\n"; // Day 3. Got Day 3.
    std::cout << " ... in: " << in << "\n\n";

    DayOfYearMod d_pre(31), d_post(31); // Day 31 for January 31

    std::cout << "Test 2. Individual Objects. \n";
    std::cout << " ... d_pre: " << d_pre << "\n";
    std::cout << " ... ++d_pre: " << ++d_pre << "\n";
    std::cout << " ... d_post: " << d_post << "\n";
    std::cout << " ... d_post++: " << d_post++ << "\n"; // This is supposed to be Jan. 31
    std::cout << "\n";

    return 0;
}

DayOfYearMod.h

#include <string>
#include <iostream>

class DayOfYearMod {

public:
    static const int dayMax;
    static const int numMonths;
    static int daysPerMonth[ ]; // One-based indexing. 1 = January
    static std::string monthNames[ ];

private:
    int numDay; // -nth day of the year
    // Results
    int numMonth;
    std::string month;
    int dayOfMonth;
    void extractDetails();

public:
    DayOfYearMod();
    DayOfYearMod(int);
    void setDay(const int);
    bool isInRange(int);
    void addToDay(int);
    void print();
    // Overloaded Operators
    DayOfYearMod operator++(int);
    DayOfYearMod& operator++();
    friend std::ostream& operator<<(std::ostream&, const DayOfYearMod&);
};

DayOfYearMod.cpp

#include <iostream>
#include "DayOfYearMod.h"

const int DayOfYearMod::dayMax = 365;
const int DayOfYearMod::numMonths = 12;

// One-based indexing. January = 1.
// Assuming no leap years.
int DayOfYearMod::daysPerMonth[DayOfYearMod::numMonths + 1] = {
        0,
        31, 28, 31, 30, 31, 30,
        31, 31, 30, 31, 30, 31
};

std::string DayOfYearMod::monthNames[DayOfYearMod::numMonths + 1] = {
        "",
        "January", "February", "March",
        "April", "May", "June",
        "July", "August", "September",
        "October", "November", "December"
};

// Constructors
DayOfYearMod::DayOfYearMod(int num) {
    numDay = 0;
    addToDay(num); // This function allows for out-of-range values.
}

// Default constructor delegated
DayOfYearMod::DayOfYearMod() : DayOfYearMod(1) { }

// PRIVATE METHODS
void DayOfYearMod::extractDetails() {
    int temp = numDay;
    for (int i = 1; i <= numMonths; i++) {
        temp = temp - daysPerMonth[i];
        if (temp <= 0) {
            numMonth = i;
            month = monthNames[i];
            dayOfMonth = temp + daysPerMonth[i];
            break;
        }
    }
}

void DayOfYearMod::addToDay(int plus) {
    this->numDay = (this->numDay + plus) % DayOfYearMod::dayMax;
    // If r == 0, then the day is the max day.
    if (this->numDay == 0) this->numDay = DayOfYearMod::dayMax;
    this->extractDetails();
}

// PUBLIC METHODS
bool DayOfYearMod::isInRange(int val) {
    if (val > 0 && val <= dayMax) {
        return true;
    } else return false;
}

void DayOfYearMod::setDay(const int val) {
    if (!isInRange(val)) {
        std::cout << "Day not in range.";
        exit(-1);
    }
    numDay = val;
    extractDetails();
}

void DayOfYearMod::print() {
    std::cout << month << " " << dayOfMonth;
}

// OVERLOADED OPERATORS
// Prefix Increment
DayOfYearMod& DayOfYearMod::operator++() {
    this->addToDay(1);
    return *this;
}

// Postfix Increment
DayOfYearMod DayOfYearMod::operator++(int) {
    this->addToDay(1);
    return *this;
}

// Output stream operator
std::ostream& operator<<(std::ostream& out, const DayOfYearMod& d) {
    out << d.month << " " << d.dayOfMonth;
    return out;
}

运行代码给了我这个......

Test 1. Inline: 
 ... in: January 1
 ... in++: January 2
 ... in: January 2
 ... ++in: January 3
 ... in: January 3

Test 2. Individual Objects. 
 ... d_pre: January 31
 ... ++d_pre: February 1
 ... d_post: January 31
 ... d_post++: February 1

1 个答案:

答案 0 :(得分:2)

// OVERLOADED OPERATORS
// Prefix Increment
DayOfYearMod& DayOfYearMod::operator++() {
    this->addToDay(1);
    return *this;
}

// Postfix Increment
DayOfYearMod DayOfYearMod::operator++(int) {
    this->addToDay(1);
    return *this;
}

这两个函数首先递增对象,然后返回新值。确实你的postincrement运算符按值而不是按引用返回(应该如此),但是返回的副本包含增量值,而不是像我们期望的那样增加前的值。

通常的后增量实现看起来更像是这样:

// Postfix Increment
DayOfYearMod DayOfYearMod::operator++(int) {
    DayOfYearMod copy(*this);
    this->addToDay(1);
    return copy;
}

(顺便说一句,你不需要在成员名字之前写this->。但是如果你知道这一点并且选择这样做就作为一种风格问题,好吧。)