3

我正在尝试做 Bjarne Stroustrup 的书“ Programming: Principles and Practice using C++ ”第 9 章末尾的练习。我从书中复制了大部分代码,只需要定义Date类的成员函数add_day(), add_month(),add_year()和重载+运算符即可使用Chrono::Date::Month枚举。

我的问题是程序可以编译,但是当我Chrono::Date::add_month()main(). add_month()是唯一在枚举上使用重载+运算符的函数。Month其他两个成员函数 (add_day()add_year()) 在main(). 当我正在做add_month()直接做的事情时main()(不使用该功能),它工作正常。

崩溃发生在 Chrono.cpp 的第 100 行,错误为“堆栈溢出”:

    Date::Month& operator + (Date::Month& m, int n) {

这是我的代码:

计时.h:

#include "../../std_lib_facilities.h"

namespace Chrono {

    class Date {
    public:
        enum Month {
            jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec
        };
        class Invalid {};   // à utiliser comme exception

        Date(int yy, Month mm, int dd); // vérifie la validité et initialise
        Date();                         // constructeur par défaut

        //opérations non modificatrices:
        int day() const {return d;}
        Month month() const {return m;}
        int year() const {return y;}

        //opérations modificatrices:
        void add_day(int n);
        void add_month(int n);
        void add_year(int n);

    private:
        int y;
        Month m;
        int d;
    };

    bool is_date(int y, Date::Month m, int d);  // vrai pour une date valide

    bool leapyear(int y);   // vrai si l'année est bissextile

    int days_in_month(Date::Month m, int y);

    bool operator == (const Date& a, const Date& b);
    bool operator != (const Date& a, const Date& b);

    ostream& operator << (ostream& os, const Date& d);

    istream& operator >> (istream& is, Date& dd);

    Date::Month& operator + (Date::Month& m, int n);
}

计时.cpp:

#include "Chrono.h"

namespace Chrono {

    // définitions des fonctions membres:

    Date::Date(int yy, Month mm, int dd)
        :y(yy), m(mm), d(dd) {
        if (!is_date(yy,mm,dd)) throw Invalid();
    }

    Date& default_date() {
        static Date dd(2001, Date::jan, 1);
        return dd;
    }

    Date::Date()
        :y(default_date().year()), m(default_date().month()), d(default_date().day()) {}

    void Date::add_day(int n) {
        if((d + n) > days_in_month(m,y)) {
            add_month(1);
            d = d + n - days_in_month(m,y);
        }
        else
            d += n;
    }

    void Date::add_month(int n) {
        //if ((m + n) > 12) {
        //  m = m + (n - 12);
        //  y += 1;
        //}
        //else 
            m = m + n;
    }

    void Date::add_year(int n) {
        if (m==feb && d==29 && !leapyear(y+n)) {
            m = mar;
            d = 1;
        }
        y += n;
    }

    bool is_date(int y, Date::Month m, int d) {
        // on suppose y valide

        if (d<0) return false;
        if(days_in_month(m,y) < d) return false;
        if(m < Date::jan || m > Date::dec) return false;
        return true;
    }

    bool leapyear(int y) {
        if (y % 4 == 0 && y % 100 > 0 || y % 400 == 0)
            return true;
        else
            return false;
    }

    int days_in_month(Date::Month m, int y) {
        int d_i_m = 31;
        switch(m) {
        case Date::feb:
            d_i_m = (leapyear(y))?29:28;
            break;
        case Date::apr: case Date::jun: case Date::sep: case Date::nov:
            d_i_m = 30;
            break;
        }
        return d_i_m;
    }

    bool operator == (const Date& a, const Date& b) {
        return a.year() == b.year() && a.month() == b.month() && a.day() == b.day();
    }

    bool operator != (const Date& a, const Date& b) {
        return !(a==b);
    }

    ostream& operator << (ostream& os, const Date& d) {
        return os << '(' << d.year() << ',' << d.month() << ',' << d.day() << ')';
    }

    istream& operator >> (istream& is, Date& dd) {
        int y, m, d;
        char ch1, ch2, ch3, ch4;
        is >> ch1 >> y >> ch2 >> m >> ch3 >> d >> ch4;
        if (!is) return is;
        if (ch1!='(' || ch2!=',' || ch3!=',' || ch4!=')') {
            is.clear(ios_base::failbit);
            return is;
        }
        dd = Date(y,Date::Month(m),d);
        return is;
    }

    Date::Month& operator + (Date::Month& m, int n) {
        return m + n;
    }

    enum Day {
        sunday, monday, tuesday, wednesay, thursday, friday, saturday
    };

    //Day day_of_week(const Date& d) {
    //  // ...
    //}

    //Day next_Sunday(const Date& d) {
    //  // ...
    //}

    //Day next_weekday(const Date& d) {
    //  // ...
    //}
}

main.cpp(工作):

#include "Chrono.h"

int main() {
    cout << Chrono::Date::jan + 1;
}

备用 main.cpp (编译但崩溃):

#include "Chrono.h"

int main() {
    Chrono::Date date;
    date.add_month(1);
}

PS:std_lib_facilities.h 定义了向量、字符串和 IO。它在这里可用。

4

1 回答 1

6
Date::Month& operator + (Date::Month& m, int n) {
    return m + n;
}

这对您来说可能看起来并不明显,但这是一个递归调用。它一直在调用自己,没有终止条件。最终,您通过无限调用此函数来填满堆栈。

于 2012-08-26T22:10:47.817 回答