1. 程式人生 > >C++運算子過載(注意點),友元(使用和優缺點)

C++運算子過載(注意點),友元(使用和優缺點)

運算子過載例項程式碼

class A{
public:
    int a,b;
    A(int _a=0,int _b=0):a(_a),b(_b){}
    A operator+(A & tmpa){
        A t;
        t.a = this->a + tmpa.a;
        t.b = this->b + tmpa.b;
        return t;
    }
    friend ostream& operator <<(ostream& os,A &tmpa){
        os << "("
<< tmpa.a << "," << tmpa.b << ")"; return os; } }; int main() { freopen("in.txt", "r", stdin); A a1(1,1); A a2(2,3); A a3 = a1 + a2; A a4 = a1.operator+(a2); cout << a1 << endl; return 0; }

過載運算子可以使用成員函式或非成員函式兩種方法

注意只能使用其中的一種方法

以運算子+為例:

作為成員函式

A operator+(A & tmpa){
        A t;
        t.a = this->a + tmpa.a;
        t.b = this->b + tmpa.b;
        return t;
    }
  • 需要有兩個運算子,因為是成員函式,所以有一個this指標隱含的傳過去,只需要一個引數就行了

在使用的時候,有如下的兩種使用方式,operator+ 類似於一個成員函式方法名,直接呼叫

A a3 = a1 + a2;

A a4 = a1.operator+(a2);

作為非成員函式

operator+ 需要指定兩個運算元,宣告為友元函式

// 宣告在函式內部
friend A operator+(const A &t1, const A &t2);

// 具體實現
A operator+(const A &t1, const A &t2)
{
    A t;
    t.a = t1.a + t2.a;
    t.b = t1.a + t2.b;
    return t;
}

在使用的時候

A a3 = a1 + a2; // 可用
A a4 = a1.operator+(a2); // 錯誤,應為opetor+不是類成員方法

友元

1 為什麼引入友元函式

實現類之間的資料共享,減少系統開銷,提高效率;使得其它的類成員函式能直接訪問該類的私有變數

缺點: 友元函式破壞了封裝機制,儘量不要使用

2 什麼時候使用友元函式

  • 運算子過載的某些場合需要友元
  • 兩個類共享資料時

3 友元函式沒有this指標,是類外的函式

友元函式的宣告可以在類的私有段或公有段,且沒有區別
可以直接呼叫友元函式,不需要通過物件或指標

友元函式的引數:
1 訪問非static成員時,需要物件作引數
2 訪問static成員時,不需要物件作引數
3 引數是全域性物件時,不需要物件作引數

運算子過載注意點

  • 過載的運算子(有些是例外情況)不必是成員函式(可以用友元函式來實現),但是必須至少有一個運算元是使用者自定義的型別(物件型別本身)。

這裡寫圖片描述

這裡寫圖片描述

class Myclass{
public:
    double f;

    Myclass(double _f = 0.0):f(_f){}
public:

    friend Myclass operator*(Myclass m, double d); // 1
    friend Myclass operator*(Myclass m, Myclass m2); // 2
    friend Myclass operator*(double d, Myclass m); // 3
    //friend Myclass operator*(double d, double d2);
};

Myclass operator*(Myclass m, double d)
{
    Myclass m2;
    m2.f = m.f * d;
    return m2;
}


Myclass operator*(double d, Myclass m)
{
    Myclass m2;
    m2.f = m.f * d;
    return m2;
}

int main()
{
    Myclass m1(2.1);
    Myclass  m2 = m1 * 3; // 對應呼叫1, 否則出現無法解析符號相關報錯
    Myclass  m3 = 4 * m1; // 對應呼叫3

    return 0;
}
  • 使用運算子時不能違反運算子原來的句法規則。例如,不能將取模運算子(%)過載成只使用一個運算元

如下,因為成員函式預設有一個this引數,乘法(*)運算子是兩個運算元,所以只有一個引數,不能有多的引數

這裡寫圖片描述

  • 過載的運算子 ,不會改變優先順序

  • 不能建立新的的運算子來過載,例如不能定義 operator**()函式來表示求冪

  • 有些運算子不能過載

這裡寫圖片描述

這裡寫圖片描述

  • 運算子過載可用成員函式,或友元函式,但是有些運算子的過載只能用 成員函式

這裡寫圖片描述