運算子過載與友元
參考:《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),也就是說,運算子左側的物件作為函式的呼叫者,後面的物件則作為實參傳遞給被呼叫的物件。
友元
友元:
- 什麼是友元:友元是一種定義在類外部的普通函式或類,但它需要在類體內進行說明,它不屬於成員函式,但是可以訪問類中的私有成員。
- 什麼時候使用友元進行運算子過載:多在過載二元運算子時使用(帶兩個引數的運算子)
示例:仍回到上面的程式碼,如果進行如下運算,程式將會報錯:沒有與這些操作匹配的“+”運算子
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;
}