背景:運算符重載談到
如果定義一個Time operator*(double n)的重載運算符
可以進行total = t1*3運算吨枉,而不可以total = 3 * t1.
OOP的解決方法就是非成員函數(shù),非成員函數(shù)不是由對象調用的纲熏,且它使用的值都是顯式參數(shù)靠汁。
total = 3 * t1與total = operator*(3王暗,t1)相關聯(lián)姊扔,原型為Time operator*(double n,const Time &)
有一類特殊的非成員函數(shù)可以訪問類的私有成員鳖枕,那就是友元函數(shù)
創(chuàng)建友元函數(shù)
- Step 1:聲明函數(shù)
原型放在類聲明中魄梯,在原型前加入關鍵字friend
friend Time operator*(double n,const Time &)
該原型意味著:
- operator*()函數(shù)在類中聲明但不是成員函數(shù),因此不能用成員運算符點來調用
- operator*()雖然不是成員函數(shù)宾符,但還是有權限使用私有成員.
- Step 2:定義函數(shù)
因為不是成員函數(shù)酿秸,所以不要用作用域解析運算符::,且不要再定義中使用關鍵字friend
Time operator*(double n,const Time & t)
{
Time sum;
sum.mins = t.mins * n;
sum.hours = sum.mins / 60 + t.hours* n;
sum.mins %= 60;
return sum;
}
然后既可以調用total = 3* t1
也可以將友元函數(shù)編寫為非友元函數(shù)魏烫,既(太……nb了)辣苏,如下代碼所示晚胡,就是反向調用非友元函數(shù)缺谴。
ps. 不要再函數(shù)原型末尾用const,因為不是成員函數(shù)磁奖,不用防止自身修改自身的行為润讥。
Time oeprator*(double n, const Time &t)
{
return t * n
}
重載<<運算符
如果不用total.Show(),而直接用cout<<total 該多好爱态,就運用到<<重載運算符.
ps. 不要再標準接口比如ostream類中進行修改副签,那會很危險讨勤。所以直接在Time類聲明讓Time類知道如何使用cout/
- 第一類<<重載運算符
因為是cout<<total 而不是total<<cout购裙,所以定義一個友元函數(shù)
void operator<<(ostream & os , const Time &t)
{
os<< t.hours << " hours" <<t.mins<<" mins"; }
然后便可以使用cout<<total ;
- 友元和非友元: 該函數(shù)不是ostream類的友元函數(shù),對ostream類無害萌狂,從始至終都是講ostream類作為整體使用档玻。而函數(shù)可以訪問Time的私有成員,所以是Time的友元函數(shù)
- cout是一個ostream類對象茫藏,cout<<Time將導致os是cout的一個別名误趴,引用cout對象。另一個對象是cerr务傲,它將輸出發(fā)送到標準輸出流(顯示屏screen)凉当。而且調用cout<<Time應該使用cout本身,所以按引用傳遞树灶。cerr<<Time 將導致os成為cerr別名纤怒。
- 第二類重載運算符
如果要使用
cout<<"trip time: " << trip<<"(wednesday)" ;
如果向上面那樣定義將行不通。
cout 操作的一點知識:
cout<<x<<y 通常是(cout<<x) << y天通,從左到右讀取泊窘。<<左邊需要的是一個ostream對象,所以cout<<x也是一個ostream對象(指向ostream對象的引用)
所以只要將定義修改成如下:
ostream & operator(ostream & os, const Time & t)
{
os<< t.hours<<" hours "<<t.mins<<" mins.";
return os;}
程序返回ostream引用像寒,傳遞一個對象引用給它烘豹,然后返回值就是傳遞給他的對象。cout<<trip,被轉換為operator<<(cout,trip);
所以cout<<"trip time:"<<trip<<" (wednesday)";
使用原理就是诺祸,先打印字符串携悯,返回cout對象,然后調用operator<<(cout,trip),然后繼續(xù)返回cout對象筷笨,然后繼續(xù)打印字符串憔鬼。
operator<<還可以將輸出寫入文件
#include<fstream>
..
ofstream fout;
fout.open(“savetime.txt");
Time trip(12,20);
fout<<trip; // operator<<(fout,trip)
對于很多運算符來說,都可以使用友元函數(shù)或非友元函數(shù)來實現(xiàn)胃夏。(除了上面提到的幾個必須用成員函數(shù)來實現(xiàn)的)
比如
Time operator+(const Time & t) const;
friend Time operator+(const Time &t1, const Time &t2) ;
這兩個功能是一樣的轴或,但只能定義一個,否則可能產生二義性仰禀。一般來說照雁,我喜歡友元函數(shù)。