我重载的 post-increment 方法没有按预期工作。为什么?
My overloaded post-increment method doesn't work as expected. Why?
我有这个 C++ class,它接受一年中的天数并将其转换为月-日格式。它工作正常,但我的问题是我重载的 post-increment 运算符没有按预期工作。
我明白了下面的代码...
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
因此,post-increment 首先将对象传递给 << 然后递增它。而pre-increment是给对象加一,然后传给<<.
但是,在下面的代码中,重载的 post-increment 方法与 pre-increment 方法的工作方式相同——据我所知,这是不应该的即将发生。这里发生了什么?
三个文件:(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
// OVERLOADED OPERATORS
// Prefix Increment
DayOfYearMod& DayOfYearMod::operator++() {
this->addToDay(1);
return *this;
}
// Postfix Increment
DayOfYearMod DayOfYearMod::operator++(int) {
this->addToDay(1);
return *this;
}
这两个函数首先递增对象,然后return新值。的确,您的后增量运算符 returns 按值而不是按引用(应该如此),但是 returned 副本包含增量值,而不是我们期望的增量前的值。
通常的后增量实现看起来更像这样:
// Postfix Increment
DayOfYearMod DayOfYearMod::operator++(int) {
DayOfYearMod copy(*this);
this->addToDay(1);
return copy;
}
(顺便说一句,您不需要在成员名称前写 this->
。但如果您知道这一点并出于风格考虑仍然选择这样做,好吧。)
我有这个 C++ class,它接受一年中的天数并将其转换为月-日格式。它工作正常,但我的问题是我重载的 post-increment 运算符没有按预期工作。
我明白了下面的代码...
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
因此,post-increment 首先将对象传递给 << 然后递增它。而pre-increment是给对象加一,然后传给<<.
但是,在下面的代码中,重载的 post-increment 方法与 pre-increment 方法的工作方式相同——据我所知,这是不应该的即将发生。这里发生了什么?
三个文件:(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
// OVERLOADED OPERATORS
// Prefix Increment
DayOfYearMod& DayOfYearMod::operator++() {
this->addToDay(1);
return *this;
}
// Postfix Increment
DayOfYearMod DayOfYearMod::operator++(int) {
this->addToDay(1);
return *this;
}
这两个函数首先递增对象,然后return新值。的确,您的后增量运算符 returns 按值而不是按引用(应该如此),但是 returned 副本包含增量值,而不是我们期望的增量前的值。
通常的后增量实现看起来更像这样:
// Postfix Increment
DayOfYearMod DayOfYearMod::operator++(int) {
DayOfYearMod copy(*this);
this->addToDay(1);
return copy;
}
(顺便说一句,您不需要在成员名称前写 this->
。但如果您知道这一点并出于风格考虑仍然选择这样做,好吧。)