1. 程式人生 > 其它 >C++:運算子過載

C++:運算子過載

技術標籤:C++c++多型

運算子過載

運算子過載規則

  • 思考:用“+”、“-”能夠實現複數的加減運算嗎?

  • 實現複數加減運算的方法 ——過載“+”、“-”運算子

  • 運算子過載是對已有的運算子賦予多重含義,使同一個運算子作用於不同型別的資料時導致不同的行為。

  • C++ 幾乎可以過載全部的運算子,而且只能夠過載C++中已經有的。

  • 不能過載的運算子:“.”、“.*”、“::”、“?:”

    • 過載之後運算子的優先順序和結合性都不會改變。
  • 運算子過載是針對新型別資料的實際需要,對原有運算子進行適當的改造。例如:

    • 使複數類的物件可以用“+”運算子實現加法;

    • 是時鐘類物件可以用“++”運算子實現時間增加1秒。

  • 過載為類的非靜態成員函式;

  • 過載為非成員函式。

過載為類成員的運算子函式定義形式

函式型別 operator 運算子(形參)
{

}
引數個數=原運算元個數-1 (後置++、–除外)

雙目運算子過載規則

  • 如果要過載 B 為類成員函式,使之能夠實現表示式 oprd1 B oprd2,其中 oprd1 為A 類物件,則 B 應被過載為 A 類的成員函式,形參型別應該是 oprd2 所屬的型別。

  • 經過載後,表示式 oprd1 B oprd2 相當於 oprd1.operator B(oprd2)

複數類加減法運算過載為成員函式

  • 要求:

    • 將+、-運算過載為複數類的成員函式。
  • 規則:

    • 實部和虛部分別相加減。
  • 運算元:

    • 兩個運算元都是複數類的物件。
  • 原始碼:

#include <iostream>
using namespace std;
class Complex {
public:
    Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) { }
    //運算子+過載成員函式
  Complex operator + (const Complex &c2) const;
    //運算子-過載成員函式
  Complex operator - (const Complex &
c2) const; void display() const; //輸出複數 private: double real; //複數實部 double imag; //複數虛部 }; Complex Complex::operator+(const Complex &c2) const{ //建立一個臨時無名物件作為返回值 return Complex(real+c2.real, imag+c2.imag); } Complex Complex::operator-(const Complex &c2) const{ //建立一個臨時無名物件作為返回值 return Complex(real-c2.real, imag-c2.imag); } void Complex::display() const { cout<<"("<<real<<", "<<imag<<")"<<endl; } int main() { Complex c1(5, 4), c2(2, 10), c3; cout << "c1 = "; c1.display(); cout << "c2 = "; c2.display(); c3 = c1 - c2; //使用過載運算子完成複數減法 cout << "c3 = c1 - c2 = "; c3.display(); c3 = c1 + c2; //使用過載運算子完成複數加法 cout << "c3 = c1 + c2 = "; c3.display(); return 0; }

在這裡插入圖片描述

前置單目運算子過載規則

  • 如果要過載 U 為類成員函式,使之能夠實現表示式 U oprd,其中 oprd 為A類物件,則 U 應被過載為 A 類的成員函式,無形參。

  • 經過載後,表示式 U oprd 相當於 oprd.operator U()

後置單目運算子 ++和–過載規則

  • 如果要過載 ++或–為類成員函式,使之能夠實現表示式 oprd++ 或 oprd-- ,其中 oprd 為A類物件,則 ++或-- 應被過載為 A 類的成員函式,且具有一個 int 型別形參。

  • 經過載後,表示式 oprd++ 相當於 oprd.operator ++(0)

過載前置++和後置++為時鐘類成員函式

  • 前置單目運算子,過載函式沒有形參

  • 後置++運算子,過載函式需要有一個int形參

  • 運算元是時鐘類的物件。

  • 實現時間增加1秒鐘。

#include <iostream>
using namespace std;
class Clock {//時鐘類定義
public: 
    Clock(int hour = 0, int minute = 0, int second = 0);
    void showTime() const;
  //前置單目運算子過載
    Clock& operator ++ ();
  //後置單目運算子過載
    Clock operator ++ (int);    
private:
    int hour, minute, second;
};

Clock::Clock(int hour, int minute, int second) {    
    if (0 <= hour && hour < 24 && 0 <= minute && minute < 60 && 0 <= second && second < 60) {
        this->hour = hour;
        this->minute = minute;
        this->second = second;
    } else
        cout << "Time error!" << endl;
}
void Clock::showTime() const {  //顯示時間
    cout << hour << ":" << minute << ":" << second << endl;
}

Clock & Clock::operator ++ () { 
    second++;
    if (second >= 60) {
        second -= 60;  minute++;
        if (minute >= 60) {
          minute -= 60; hour = (hour + 1) % 24;
        }
    }
    return *this;
}

Clock Clock::operator ++ (int) {
    //注意形參表中的整型引數
    Clock old = *this;
    ++(*this);  //呼叫前置“++”運算子
    return old;
}

int main() {
    Clock myClock(23, 59, 59);
    cout << "First time output: ";
    myClock.showTime();
    cout << "Show myClock++:    ";
    (myClock++).showTime();
    cout << "Show ++myClock:    ";
    (++myClock).showTime();
    return 0;
}

在這裡插入圖片描述

運算子過載為非成員函式

有些運算子不能過載為成員函式,例如二元運算子的左運算元不是物件,或者是不能由我們過載運算子的物件

運算子過載為非成員函式的規則

  • 函式的形參代表依自左至右次序排列的各運算元。

  • 過載為非成員函式時

  • 引數個數=原運算元個數(後置++、–除外)

  • 至少應該有一個自定義型別的引數。

  • 後置單目運算子 ++和–的過載函式,形參列表中要增加一個int,但不必寫形參名。

  • 如果在運算子的過載函式中需要操作某類物件的私有成員,可以將此函式宣告為該類的友元。

運算子過載為非成員函式的規則

  • 雙目運算子 B過載後,

表示式oprd1 B oprd2

等同於operator B(oprd1,oprd2 )

  • 前置單目運算子 B過載後,

表示式 B oprd

等同於operator B(oprd )

  • 後置單目運算子 ++和–過載後,

表示式 oprd B

等同於operator B(oprd,0 )

過載Complex的加減法和“<<”運算子為非成員函式

  • 將+、-(雙目)過載為非成員函式,並將其宣告為複數類的友元,兩個運算元都是複數類的常引用。
  • 將<<(雙目)過載為非成員函式,並將其宣告為複數類的友元,它的左運算元是std::ostream引用,右運算元為複數類的常引用,返回std::ostream引用,用以支援下面形式的輸出:
cout << a << b;

該輸出呼叫的是:

operator << (operator << (cout, a), b);

原始碼

#include <iostream>
    using namespace std;

    class Complex {
    public:
        Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) { }  
        friend Complex operator+(const Complex &c1, const Complex &c2);
        friend Complex operator-(const Complex &c1, const Complex &c2);
        friend ostream & operator<<(ostream &out, const Complex &c);
    private:    
        double real;  //複數實部
        double imag;  //複數虛部
    };

    Complex operator+(const Complex &c1, const Complex &c2){
        return Complex(c1.real+c2.real, c1.imag+c2.imag); 
    }
    Complex operator-(const Complex &c1, const Complex &c2){
        return Complex(c1.real-c2.real, c1.imag-c2.imag); 
    }

    ostream & operator<<(ostream &out, const Complex &c){
        out << "(" << c.real << ", " << c.imag << ")";
        return out;
    }

    int main() {    
        Complex c1(5, 4), c2(2, 10), c3;    
        cout << "c1 = " << c1 << endl;
        cout << "c2 = " << c2 << endl;
        c3 = c1 - c2;   //使用過載運算子完成複數減法
        cout << "c3 = c1 - c2 = " << c3 << endl;
        c3 = c1 + c2;   //使用過載運算子完成複數加法
        cout << "c3 = c1 + c2 = " << c3 << endl;
        return 0;
    }