1. 程式人生 > >類的預設成員函式---都是原始碼

類的預設成員函式---都是原始碼

class Date
{
public:                //沒用初始化列表
	Date(int year = 1999,int month = 1,int day = 1)//最好定義為全預設 
	{
		//檢查日期是否合法

		if(year < 1900
			|| month < 1 || month > 12
			|| day < 1 || day > GetMonthDay(year,month))
		{
			cout<<"非法日期"<<endl;

		}

		_year = year;
		_month = month;
		_day = day;
	}

	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	//d2 = d3  =>  d2.operator(&d2,d3)
	Date& operator=(const Date& d)     //有倆個引數,但只寫一個,因為還有一個引數是隱含的this指標。
	{
		if(this != &d)          //是否是自己給自己賦值。沒有什麼很壞的影響,只是白做了而已。
		{
			this->_year = d._year;             //this可以顯示的寫出來,也可以不寫,寫著this在這裡方便於觀察。
			this->_month = d._month;
			this->_day = d._day;
		}
		return *this;   //賦值操作已經完成,為什麼有個返回值?因為賦值運算子的過載支援三個數,i=j=k;k先賦給j後有一個返回值j,將這個返回值賦給i,返回的是同類型物件,所以型別為Date
		//但此時如果沒有給函式型別加引用,就是傳值返回,不會直接返回,會建立一個臨時物件。。會多一次拷貝構造,拷貝一個臨時物件,再拿這個臨時物件做返回
		//傳值返回:返回的是一個臨時物件
		//傳引用返回:返回的物件出了作用域還在
	}

	//d1 < d2  會先去全域性區找有沒有小於的運算子過載,沒有的話就到類中找,找到了,其實就轉化為->d1.operator<(&d1,d2)
	//bool operator<(const Date& x1)  //在類外面我們實現了第一次的operator,對類外進行改進
 //   {
	//	if(_year < x1._year)
	//	{
	//		return true;
	//	}
	//	else if(_year == x1._year)
	//	{
	//		if(_month < x1._month)
	//		{
	//			return true;
	//		}
	//		else if(_month == x1._month)
	//		{
	//			if(_day < x1._day)
	//				return true;
	//		}
	//	}
	//	return false;
 //   }

	//d1+10
	//Date operator+(int day)  //自己寫的
	//{
	//	/*int day = day + _day;      
	//	while(day > GetMonthDay(_year,_month))
	//	{
	//		day = day - GetMonthDay(_year,_month);
	//		_month++;

	//		if(_month > 12)
	//		{
	//			_year++;
	//			_month = 1;
	//			_day = 1;
	//		}
	//	}
	//	return *this;*/
	//}

	//Date operator+(int day)      
	//{
	//	Date ret(*this);        //+運算子不能改變原有的this的值,所以需要一個臨時變數和this有相同的空間和值。
 //       
	//	ret._day += day;
	//	while(ret._day > GetMonthDay(ret._year,ret._month))
	//	{
	//		ret._day -= GetMonthDay(ret._year,ret._month);
	//		ret._month++;

	//		if(ret._month == 13)
	//		{
	//			ret._year++;
	//			ret._month = 1;
	//		}
	//	}
	//	return ret;   //返回一個臨時變數,所以用傳值返回。
	//}
	////d1 += 10
	//Date& operator+=(int day)
	//{
	//	*this = *this + day;    //調一次+再調一次賦值
	//	return *this;     //這樣的前提是先實現+,但是先實現+=好,因為+裡既拷貝還要開空間還要賦值
	//}

	Date& operator+=(int day)
	{
		if(day < 0)
		{
			return *this -= -day;
		}
		_day += day;
		while(_day > GetMonthDay(_year,_month))
		{
			_day -= GetMonthDay(_year,_month);
			_month++;

			if(_month == 13)
			{
				_year++;
				_month = 1;
			}
		}
		return *this;
	}

	//d+10
	Date operator+(int day)
	{
		Date ret(*this);//*this 是d
		ret += day;

		return ret;
	}

	//自己寫的
	/*Date operator-(int day)
	{
		Date ret(*this);
		
		ret._day = day - ret._day;
		while(ret._day > GetMonthDay(ret._year,ret._month))
		{
			ret._day = ret._day - GetMonthDay(ret._year,ret._month);
			ret._month--;

			if(ret._month == 0)
			{
				ret._year--;
				ret._month = 12;
			}
		}
		return ret;
	}
	Date& operator-=(int day)
	{
		*this = *this - day;
		return *this;
	}*/

	//上課
	/*Date operator-(int day)
	{
		Date ret(*this);

		ret._day -= day;
		while(ret._day <= 0)
		{
			ret._month--;
			ret._day += GetMonthDay(ret._year,ret._month);

			if(ret._month == 0)
			{
				ret._year--;
				ret._month = 12;
			}
		}
		return ret;
	}*/
	Date& operator-=(int day)
	{
		if(day < 0)
		{
			return *this += -day;
		}
		_day -= day;
		while(_day <= 0)
		{
			--_month;
			if(_month == 0)
			{
				_year--;
				_month = 12;
			}
			_day+=GetMonthDay(_year,_month);
		}
		return *this;
	}
	Date operator-(int day)
	{
		Date ret(*this);

		ret -= day;
		return ret;
	}
	//d1 -d2
	int operator-(const Date& d)     //不加const d2會被改
	{
		int flag = 1;
		Date max = *this;
		Date min = d;

		if(*this < d)
		{
			max = d;
			min = *this;
			flag = -1;
		}
		int day = 0;
		while(min < max)
		{
			++(min);
			++day;
		}
		return day*flag;
	}

	//++d  => d.operator++(&d)
	Date& operator++()    //前置   返回值是++後的值
	{
		*this += 1;
		return *this;
	}

	//d++  => operator++(&d,0)
	Date operator++(int)  //後置    int只是為了與前置做一個區分   返回的是++前的值
	{
		Date ret(*this);
		*this += 1;
		return ret;
	}

	Date& operator--()
	{
		*this -= 1;
		return *this;
	}
	Date operator--(int)
	{
		Date ret(*this);
		*this -= 1;
		return ret;
	}


	bool operator>(const Date& d)
	{
		if(_year > d._year)
		{
			return true;
		}

		else if(_year == d._year)
		{
			if(_month > d._month)
			{
				return true;
			}
			else if(_month == d._month)
			{
				if(_day > d._day)
					return true;
			}
		}
		return false;
	}
	bool operator==(const Date& d)
	{
		return _year == d._year
			&& _month == d._month
			&&_day == d._day;
		 
	}
	bool operator>=(const Date& d)
	{
		return *this > d || *this == d;
	}
	bool operator<(const Date& d)
	{
		return !(*this >= d);
	}
	bool operator<=(const Date& d)
	{
		return !(*this > d);
	}
	bool operator!=(const Date& d)
	{
		return !(*this == d);
	}

	//~Date()         //這個日期類可以不去清理,但有的類需要清理,比如順序表
	//{
	//	//清理工作
	//	cout<<"~Date()"<<endl;
	//}
	void Display()
	{
		cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	}
	int GetMonthDay(int year,int month)
{
	 static int MonthDay[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
	 int day = MonthDay[month];
		 if(month == 2
			 && ((year%400 == 0) || (year%4 == 0 && year%100 != 0)))
		 {
			 day += 1;
		 }
		 return day;
}
private:
	int _year;
	int _month;
	int _day;
};

//bool operator<(const Date& x1,const Date& x2)  //要穿引用返回;如果傳值雖然不會無窮遞迴,但傳值代價大,要開闢空間還要調拷貝建構函式。
//	//並且比較完不會改變x1x2所以最好加一個const  //引用做引數提高效率,提高效能
//	//這個函式之所以完成,是因為吧成員變數定義為了公有,但公有會破壞C++封裝性,可是定義為私有我這個函式就跑不了。。在類外不可訪問,那就放在類中
//	//但直接放在類中又有錯誤:operator<的引數太多   
//{
//	if(x1._year < x2._year)
//	{
//		return true;
//	}
//	else if(x1._year == x2._year)
//	{
//		if(x1._month < x2._month)
//		{
//			return true;
//		}
//		else if(x1._month == x2._month)
//		{
//			if(x1._day < x2._day)
//				return true;
//		}
//	}
//	return false;
//}

void test()
{
	Date d1(2018,9,20);
	Date d2(2019,2,28);
	d2.Display();
	cout<<d2-d1<<endl;
	/*d1 = d2 - 20;
	d1.Display();

	(++d1).Display();
	(d1++).Display();
	(--d2).Display();
	(d2--).Display();*/
	//Date d2(2018,2,2);
	//
	// 
	//cout<<d1.operator<(d2)<<endl;  //(<<優先順序高於<)
	////cout<<operator<(d1,d2)<<endl;  
	//d2 = d1;
	//d2.Display();
	//Date d2(2018,2,29);
}