1. 程式人生 > >運算子過載與友元

運算子過載與友元

參考:《C++Primer Plus》第六版

計算時間:一個運算子過載示例

先給段程式碼:

#include<iostream>
#include<string>
using namespace std;
class Time {
private:	
	int hours;
	int minutes;
public:
	Time(int hr = 0, int min = 0) :hours(hr), minutes(min) {}
	void AddMin(int m) { minutes += m;hours += minutes / 60;minutes %= 60; }
	void AddHr(int h) { hours += h; }
	void Reset(int h = 0, int m = 0) { hours = h; minutes = m; }
	Time Sum(const Time &t)const { 
		Time sum;
		sum.minutes = minutes + t.minutes;
		sum.hours = t.hours + hours + sum.minutes / 60;
		sum.minutes %= 60;
		return sum;
	}
	void Display() { cout << hours << ' ' << minutes << endl; }
	~Time() {}
};
int main()
{
	Time t1(3, 55), t2(2, 6), tt;
	tt = t1.Sum(t2);
	tt.Display();
	system("pause");
	return 0;
}

這段程式碼用來計算兩個時間的加和,需要使用函式物件的方式進行呼叫並賦值。我們如果想要用加減號等進行時間的計算,這就引入了運算子過載的概念。C++允許將運算子過載到使用者定義的型別,例如,允許使用+將兩個物件相加。

運算子過載

做法:
將上面程式碼Time類中的Time Sum(const Time &t)const 這段宣告改為 Time operator+(const Time &t)const即可。
tips:

  • operator中文釋義:運算子

  • 過載的一般形式:<返回型別說明符> operator <運算子符號>(<引數表>) { … }

  • 在主函式中呼叫時,tt = t1 + t2 相當於如下語句: tt = t1.operator+(t2),也就是說,運算子左側的物件作為函式的呼叫者,後面的物件則作為實參傳遞給被呼叫的物件。

友元

友元:

  1. 什麼是友元:友元是一種定義在類外部的普通函式或類,但它需要在類體內進行說明,它不屬於成員函式,但是可以訪問類中的私有成員。
  2. 什麼時候使用友元進行運算子過載:多在過載二元運算子時使用(帶兩個引數的運算子)

示例:仍回到上面的程式碼,如果進行如下運算,程式將會報錯:沒有與這些操作匹配的“+”運算子

tt = 3 + t2;

為什麼呢?不妨將這個式子轉化為另外一種形式:tt = 3.operator(t2)
這樣就很明瞭了!很顯然,3不是一個Time型的物件,因此無法使用Time類的成員函式。

友元的引入

針對上面提出的問題,可能想到的一種解決措施是在外部新建立一個非成員函式,它的宣告如下:

Time operator+(int n,const Time &t);

隨之而來的問題是,基於類的封裝性,外部非成員函式不能直接訪問類的私有資料。那麼該如何做呢?回顧上面關於友元的定義,我們發現可以使用友元來解決這個問題。
步驟:
(1)類中的宣告:

friend Time operator+(int n, const Time &t);

類外的定義:
需要特別強調的是,因為友元函式不是成員函式,因此在外部的定義中無需加friend

Time operator+(int n, const Time &t)
{
	Time sum;
	sum.hours = n + t.hours;
	sum.minutes = t.minutes;
	return sum;
}

常用的友元:過載<<運算子

這裡由於時間原因簡寫,等有時間補上。
對於count<<t1<<endl;
其過載的類內宣告:
friend ostream & operator<<(ostream &os, const Time &t);
外部定義:

ostream & operator<<(ostream &os, const Time &t)	//因為cout是ostream物件,故返回型別為ostream的引用
{
	os << t.hours << ' ' << t.minutes;
	return os;
}

全部程式碼:

#include<iostream>
#include<string>
using namespace std;
class Time {
private:	
	int hours;
	int minutes;
public:
	Time(int hr = 0, int min = 0) :hours(hr), minutes(min) {}
	void AddMin(int m) { minutes += m;hours += minutes / 60;minutes %= 60; }
	void AddHr(int h) { hours += h; }
	void Reset(int h = 0, int m = 0) { hours = h; minutes = m; }
	/*Time operator+(const Time &t)const { 
		Time sum;
		sum.minutes = minutes + t.minutes;
		sum.hours = t.hours + hours + sum.minutes / 60;
		sum.minutes %= 60;
		return sum;
	}*/
	friend ostream & operator<<(ostream &os, const Time &t);
	void Display() { cout << hours << ' ' << minutes << endl; }
	~Time() {}
};
int main()
{
	Time t1(3, 55), t2(2, 6), tt;
	//tt.Display();
	cout << t1 << endl;
	system("pause");
	return 0;
}
ostream & operator<<(ostream &os, const Time &t)	//因為cout是ostream物件,故返回型別為ostream的引用
{
	os << t.hours << ' ' << t.minutes;
	return os;
}