Программирование. Принципы и практика использования C++ Исправленное издание, стр. 136
Month m; int d;};bool is_date(int y, Date::Month m, int d); // true для корректных датbool leapyear(int y); // true, если 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);} // ChronoОпределения находятся в файле
Chrono.cpp// Chrono.cppnamespace Chrono {// определения функций-членов: 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); // начало XXI века return dd; } Date::Date() :y(default_date().year()), m(default_date().month()), d(default_date().day()) { } void Date:: add_day(int n) { // ... } void Date::add_month(int n) { // ... } void Date::add_year(int n) { if (m==feb && d==29 && !leapyear(y+n)) { // помните о високосных годах! m = mar; // 1 марта вместо // 29 февраля d = 1; } y+=n; } // вспомогательные функции: bool is_date(int y, Date::Month m, int d) { // допустим, что y — корректный объект if (d<=0) return false; // d должна быть положительной if (m < Date::jan || Date::dec < m) return false; int days_in_month = 31; // большинство месяцев состоит из 31 дня switch (m) { case Date::feb: // продолжительность февраля варьирует days_in_month = (leapyear(y)) ? 29:28; break; case Date::apr: case Date::jun: case Date::sep: case Date::nov: days_in_month = 30; // остальные месяцы состоят из 30 дней break; } if (days_in_month<d) return false; return true; } bool leapyear(int y) { // см. упражнение 10 } 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); // установлен неправильный бит