物件導向 運算子過載 友元函式

2021-07-05 01:27:40 字數 3424 閱讀 2667

如果今天早上在priggs賬戶上花費了2小時35分鐘,下午又花費了2小時40分鐘,則總共花了多少時間呢?這個示例與加法概念很吻合,但要相加的單位(小時與分鐘的混合)與內建型別不匹配。我們介紹一種解決辦法——運算子過載。

先來看如下time類的宣告:

#ifndef mytime_h_

#define mytime_h_

#include using namespace std;

class time

friend ostream & operator << (ostream & os, const time & t);

}; #endif

下面的**是對time中方法的實現:

#include "mytime.h"

time::time()

time::time(int h, int m)

void time::addmin(int m)

void time::addhr(int h)

void time::reset(int h, int m)

time time::operator + (const time & t) const

time time::operator - (const time & t) const

time time::operator * (double mult) const

ostream & operator << (ostream & os, const time & t)

我們對以上程式作如下說明:

1. 運算子過載限制

多數c++運算子都可以用如上的方式進行過載。過載的運算子不必是成員函式(有些例外情況),但必須至少有乙個運算元是使用者定義的型別。下面詳細介紹c++對使用者定義的運算子過載的限制。

(1) 過載後的運算子必須至少有乙個運算元是使用者定義的型別,這將防止使用者為標準型別過載運算子。因此,不能將減法運算子(-)過載為計算兩個double值的和,而不是他們的差。雖然這種限制將對創造性有所影響,但可以確保程式正常執行。

(2) 使用運算子時不能違反運算子原來的句法規則。例如,不能將求模運算子(%)過載成使用乙個運算元。同樣,不能修改運算子的優先順序。因此,如果將加號運算子過載成將兩個類相加,則新的運算子與原來的加號具有相同的優先順序。

(3) 不能定義新的運算子。例如,不能定義operator ** ()函式來表示求冪。

(4) 不能過載下面的運算子:

sizeof:sizeof運算子。

.:成員運算子。

.*:成員指標運算子。

:::作用域解析運算子。

?::條件運算子。

typeid:乙個rtti運算子。

const_cast:強制型別轉換運算子。

dynamic_cast:強制型別轉換運算子。

reinterpret_cast:強制型別轉換運算子。

static_cast:強制型別轉換運算子。

一言以蔽之,帶點的運算子不能過載。

(5) 大多數運算子都可以通過成員或非成員函式進行過載,但下面的運算子只能通過成員函式進行過載:

=:賦值運算子。

():函式呼叫運算子。

:下標運算子。

->:通過指標訪問類成員的運算子。

2. 友元函式

在上面的程式中,如果我們不定義函式friend time operator * (double m, const time & t);那麼,我們進行計算a = b * 2.75;將被轉換為a = b.operator(2.75);但是語句a = 2.75 * b呢?從概念上講,這兩個表示式計算結果是相同的,但2.75*b不對應於成員函式,因為2.75不是time型別的物件。記住,左側的運算元應是呼叫物件,但2.75不是物件。因此,編譯器不能使用成員函式呼叫來替換該表示式。

解決這一問題的一種方法是告知使用者不能寫成2.75*b,這是一種對伺服器友好-客戶警惕的(server-friendly, client-beware)解決方案。另一種解決方法是使用非成員函式(記住,大多數運算子都可以通過成員函式來過載)。

使用非成員函式可以按所需的順序獲得運算元(先是double,然後是time),但這引發了乙個新問題:非成員函式不能直接訪問類的私有資料,至少常規的非成員函式不能訪問。然而,有一類特殊的非成員函式可以訪問類的私有成員,它們被稱為友元函式。

(1) 建立友元

建立友元函式的第一步是將其原型放在類宣告中,並在原型宣告前加上關鍵字friend:

friend time operator * (double m, const time & t);  // goes in class declaration
該原型意味著下面兩點:

雖然operator*()函式是在類宣告中宣告的,但它不是成員函式,因此不能使用成員運算子來呼叫;

雖然operator*()函式不是成員函式,但它與成員函式的訪問許可權相同。

第二步是編寫函式定義。因為它不是成員函式,所以不要使用time::限定符。另外,不要在定義中使用關鍵字friend。

(2) 友元是否有悖於oop

乍一看,您可能會認為友元違反了oop資料隱藏的原則,因為友元機制允許非成員訪問私有資料。然而,這個觀點太片面了。相反,應將友元函式看作類的擴充套件介面的組成部分。例如,從概念上看,double乘以time和time乘以double是完全相同的。也就是說,前乙個要求有友元函式,後乙個使用成員函式,這是c++句法的結果,而不是概念上的差別。通過使用友元函式和類方法,可以用同乙個使用者介面表達這兩種操作。另外請記住,只有類宣告可以決定哪乙個函式是友元,因此類宣告仍然控制了哪些函式可以訪問私有資料。總之,類方法和友元只是表達類介面的兩種不同機制。

(3) 常用的友元:過載《運算子

要使用time類知道使用cout,必須使用友元函式。這是什麼原因呢?因為下面這樣的語句使用兩個物件,其中第乙個是ostream類物件(cout):

cout << trip;
如果使用乙個time成員函式來過載<<,time物件將是第乙個運算元,就像使用成員函式過載*運算子那樣。這意味著必須這樣使用<<:

trip << cout;
這樣會令人迷惑。

運算子過載,友元函式

運算子過載 include using namespace std class cint cint const cint timp public cint operator const cint timp const cint add const cint timp const cint add c...

友元運算子過載

運算子就是一種特殊的函式 運算子過載可以是普通函式 const money operator const money a1,const money a2 可以是成員函式 const money operator const money a2 const 當二元運算子作為成員函式進行過載時,只有乙個引...

8 1 2 運算子過載(友元函式)

程式頭部注釋開始 程式的版權和版本宣告部分 檔名稱 實現複數類中的運算子過載 作 者 張傳新 完成日期 2012 年04 月07 日 版 本 號 1.0 對任務及求解方法的描述部分 輸入描述 問題描述 定義乙個複數類過載運算子 使之能用於複數的加減乘除。程式輸出 程式頭部的注釋結束 includeu...