到底是以成員函式還是全域性函式的形式過載運算子?

2021-10-09 17:30:19 字數 1579 閱讀 6103

//全域性

friend complex operator+(

const complex &c1,

const complex &c2)

;//成員,記得加=號,「+=」

complex &

operator+=

(const complex &c)

;

先來看b = a + 1.1;,實際上會被轉換為b = operator+(a, 1.1);這樣的形式進行呼叫;因為存在轉換建構函式,並且第乙個引數為 double,那麼編譯器就會將 1.1 轉換為乙個匿名 complex 物件complex(1.1),進而在運算子過載函式內部將它們兩個的實部,虛部相加,然後返回乙個匿名 complex 物件並賦值給 b;

而對於b = 2.2 + a;,也是一樣的道理,被轉換為b = operator+(2.2, a);這樣的形式,然後又呼叫轉換建構函式將 2.2 轉換為乙個匿名 complex 物件complex(2.2),後面的步驟同上;

對於b = a + 1.1;,被轉換為b = a.operator+(1.1);,1.1 也是被轉換為complex(1.1);

對於b = 2.2 + a;,被轉換為b = (2.2).operator+(a);,這很顯然是不正確的,進而編譯報錯;

理由

以全域性函式的形式過載 +,是為了保證 + 運算子的運算元能夠被對稱的處理;換句話說,小數(double)在 + 左邊和右邊都是正確的;

理由:

我們首先要明白,運算子過載的初衷是給類新增新的功能,方便類的運算,它作為類的成員函式是理所應當的,是首選的;不過,類的成員函式不能對稱地處理資料,程式設計師必須在(參與運算的)所有型別的內部都過載當前的運算子;

以上面的情況為例,我們必須在 complex 和 double 內部都過載 + 運算子,這樣做不但會增加運算子過載的數目,還要在許多地方修改**,這顯然不是我們所希望的,所以 c++ 進行了折中,允許以全域性函式(友元函式)的形式過載運算子;

採用全域性函式能使我們定義這樣的運算子,它們的引數具有邏輯的對稱性;

與此相對應的,把運算子定義為成員函式能夠保證在呼叫時對第乙個(最左的)運算物件不出現型別轉換,也就是上面提到的「c++ 不會對呼叫成員函式的物件進行型別轉換」;

有一部分運算子過載既可以是成員函式也可以是全域性函式,雖然沒有乙個必然的、不可抗拒的理由選擇成員函式,但我們應該優先考慮成員函式,這樣更符合運算子過載的初衷;

另外有一部分運算子過載必須是全域性函式,這樣能保證引數的對稱性;除了 c++ 規定的幾個特定的運算子外,暫時還沒有發現必須以成員函式的形式過載的運算子;c++ 規定,箭頭運算子->、下標運算子、函式呼叫運算子()、賦值運算子=只能以成員函式的形式過載;

全域性函式和成員函式

class test1 public test1 this,int a,int b 全域性函式形式 test1 int a 0,int b 0 this a a this b b public int a int b public 成員函式 test1 t add test1 t2 test1 t3...

全域性函式VS成員函式

1 include 2 3using namespace std 45 class test613 intgeta 1417 intgetb 1821 22 test add test t2 2328 void print 2933 protected 34 private 35 inta,b 36...

c 成員函式和全域性函式的區分

include using namespace std 設計乙個立方體的類,求出立方體的面積和體積 分別用全域性函式和成員函式進行判斷兩個立方體是否相同 class cube 獲取長 intget l 設定寬 void set w int w 獲取寬 intget w 設定高 void set h ...