#include <iostream>
using namespace std;

//class defined page 225
class Date {
private:                                 //implied if not specified
                                         //in a class
   int d, m, y;
   static Date default_date;             //class variable
   int leapyear(int yy);                 //page 231 required function
public:                                  //public interfaces of the class
   Date (int dd, int mm, int yy);        //constructor with default arguments
   static void set_default(int dd, int mm, int yy); //class method
   Date& add_year(int n);			 //add n years
   Date& add_month(int n);               //add n months
   Date& add_day(int n);                 //add n days
   int day() const { return d; }         //method cannot modify state of a Date
   int month() const { return m; }
   int year() const;                     //const member defined outside class
};

Date Date::default_date(16, 12, 1770);   //definition of Date::default_date

void Date::set_default(int d, int m, int y) //definition of Date::set_default
{
	default_date = Date(d, m, y);          //assign a new value to default_date
}

Date::Date(int dd=0, int mm=0, int yy=0) //defined page 227
{
	this->d = dd ? dd : default_date.d;
	this->m = mm ? mm : default_date.m;
	this->y = yy ? yy : default_date.y;
	// check that date is valid code needed
}

inline int Date::leapyear(int yy)
{
	return (yy%4);
}

inline Date& Date::add_day(int n)
{
	if (31 >= (d + n))
	{
		d += n;
	}
	else
	{
		d = (d+n)%31;
		m = m + (n/31) +1;
	}
	return *this;
}

inline Date& Date::add_month(int n)
{
	if (12 >= (m + n))
	{
		m += n;
	}
	else
	{
		m = (m+n)%12;
		y = y + (n/12)+1;
	}
	return *this;
}

inline Date& Date::add_year(int n)
{
	if ((29 == d) && (2 == m) && !leapyear(y+n)) //beware Feb 29
	{
		d = 1;
		m = 3;
	}
	y += n;
	return *this;
}

inline int Date::year() const     //const member defined outside class
{ 
	return y; 
}

void f(Date & d, const Date& cd) 
{
	Date today = d;               //class object copied by assignment
	cout << "Today is: " 
	     << today.month() << "/" 
	     << today.day()   << "/"
	     << today.year()  << endl;
	
	Date::set_default(2,7,2002);  //Call Data's static member function
	Date my_birthday;
	cout << "My Birthday is: " 
	     << my_birthday.month() << "/" 
	     << my_birthday.day()   << "/"
	     << my_birthday.year()  << endl;
	
	Date date2(1,1);
	cout << "Date2 is: " 
	     << date2.month() << "/" 
	     << date2.day()   << "/"
	     << date2.year()  << endl;
	
	Date advance1 = today;        //initialization by copy
	advance1.add_day(1).add_month(1).add_year(1); //page 230 expression
	cout << "Advance1 is: " 
	     << advance1.month() << "/" 
	     << advance1.day()   << "/"
	     << advance1.year()  << endl;	
}

int main()
{	
	Date mydate;
	Date Indep_Day(4,7,1776);
     f(mydate, Indep_Day);
}

