C++中的運(yùn)算符重載

技術(shù)交流QQ群:1027579432,歡迎你的加入!

1.Cpp中的重載運(yùn)算符和重載函數(shù)

  • C++允許在同一作用域中的某個函數(shù)和運(yùn)算符指定多個定義,分別稱為函數(shù)重載和運(yùn)算符重載。重載聲明是指一個與之前已經(jīng)在該作用域內(nèi)聲明過的函數(shù)或方法具有相同名稱的聲明,但是它們的參數(shù)列表和定義(實現(xiàn))不相同。當(dāng)調(diào)用一個重載函數(shù)或重載運(yùn)算符時,編譯器通過調(diào)用使用的參數(shù)類型與定義中的參數(shù)類型進(jìn)行比較,決定選用最合適的定義。選擇最合適的重載函數(shù)或重載運(yùn)算符的過程,稱為重載決策。

2.函數(shù)重載

  • 在同一個作用域內(nèi),可以聲明幾個功能類似的同名函數(shù),但是這些同名函數(shù)的形式參數(shù)(指參數(shù)的個數(shù)、類型或者順序)必須不同。您不能僅通過返回類型的不同來重載函數(shù)。函數(shù)重載的實例如下,其中print()函數(shù)就是重載函數(shù):
        #include "iostream"
        #include "cstring"
    
        using namespace std;
    
    
        class A{
            public: 
                void print(int i){
                    cout << "整數(shù)為: " << i << endl;
                }
                void print(double d){
                    cout << "浮點(diǎn)數(shù)為: " << d << endl;
                }
                void print(char c[]){
                    cout << "字符串為: " << c << endl;
                }
        };
    
    
    
    
        int main(){
            A a;
            // 輸出整數(shù)
            a.print(2);
            // 輸出浮點(diǎn)數(shù)
            a.print(3.14);
            // 輸出字符串
            char c[] = "Hello Curry";
            a.print(c);
            cout << "----------------------------------------------\n";
            return 0;
        }
    
  • 構(gòu)造函數(shù)可以根據(jù)參數(shù)的不同實現(xiàn)函數(shù)重載,而析構(gòu)函數(shù)沒有參數(shù),對于一個類來說也是唯一的,所以是不能重載

3.運(yùn)算符重載

  • 可以重定義或重載大部分C++內(nèi)置的運(yùn)算符。這樣,就能使用自定義類型的運(yùn)算符。重載的運(yùn)算符是帶有特殊名稱的函數(shù),函數(shù)名是由關(guān)鍵字operator和其后面要重載的運(yùn)算符符號構(gòu)成的。與其他函數(shù)一樣,重載運(yùn)算符有一個返回類型和一個參數(shù)列表。例如:
        Box operator+(const Box&);
    
  • 聲明加法運(yùn)算符用于把兩個Box對象相加,返回最終的Box對象。大多數(shù)的重載運(yùn)算符可被定義為普通的非成員函數(shù)或者被定義為類成員函數(shù)。如果我們定義上面的函數(shù)為類的非成員函數(shù),那么我們需要為每次操作傳遞兩個參數(shù),如下所示:
        Box operator+(const Box&, const Box&);
    
  • 運(yùn)算符重載的實例,對象作為參數(shù)進(jìn)行傳遞,對象的屬性使用 this 運(yùn)算符進(jìn)行訪問,如下所示:
        // 運(yùn)算符重載
        class Box{
            public:
                double getVolume(){
                    return length * width * height;
                }
                void setLength(int len){
                    length = len;
                }
                void setWidth(int wid){
                    width = wid;
                }
                void setHeight(int hei){
                    height = hei;
                }
            // 運(yùn)算符重載:用于把兩個box對象相加
                Box operator+(const Box& b){
                    Box box;
                    box.length = this->length + b.length;
                    box.width = this->width + b.width;
                    box.height = this->height + b.height;
                    return box;
                }
            private:
                int length;
                int width;
                int height;
        };
    
        int main(){
            Box box1;
            Box box2;
            Box box3;
            double volume = 0.0;
            box1.setLength(6.0);
            box1.setWidth(7.0);
            box1.setHeight(5.0);
    
            box2.setLength(12.0);
            box2.setWidth(13.0);
            box2.setHeight(10.0);
    
            volume = box1.getVolume();
            cout << "box1的體積是: " << volume << endl;
            volume = box2.getVolume();
            cout << "box2的體積是: " << volume << endl;
    
            box3 = box1 + box2;
            volume = box3.getVolume();
            cout << "box3的體積是: " << volume << endl;
            cout << "----------------------------------------------\n";
            return 0;
        }
    

4.可重載運(yùn)算符與不可重載運(yùn)算符

  • 可重載運(yùn)算符列表如下:


    可重載運(yùn)算符.png
  • 不可重載運(yùn)算符列表如下:


    不可重載運(yùn)算符.png

5.運(yùn)算符重載實例

運(yùn)算符重載實例.png

5.1 一元運(yùn)算符重載

  • 一元運(yùn)算符只對一個操作數(shù)進(jìn)行操作,下面是一元運(yùn)算符的實例:
    • ++和--運(yùn)算符重載
          // ++與--運(yùn)算符重載
          class Time{
              private:
                  int hours;
                  int minutes;
              public:
                  Time(){
                      hours = 0;
                      minutes = 0;
                  }
                  Time(int h, int m): hours(h), minutes(m){
                      cout << "Time類對象的構(gòu)造函數(shù)\n";
                  }
                  void display(){
                      cout << "H:" << hours << " M:" << minutes << endl;
                  }
                  // 重載前綴遞增++運(yùn)算符
                  Time operator++(){
                      ++minutes;  // 對象加 1
                      if(minutes >= 60){
                          ++hours;
                          minutes-= 60;
                      }
                      return Time(hours, minutes);
                  }
                  // 重載后綴遞增++運(yùn)算符
                  Time operator++(int){
                      Time T(hours, minutes);  // 保存原始值
                      ++minutes;  // 對象加 1
                      if(minutes >= 60){
                          ++hours;
                          minutes-= 60;
                      }
                      return T;  // 返回舊的原始值
                  }
      
          };
      
      • ++和--運(yùn)算符重載注意點(diǎn):
        • 遞增和遞減一般是改變對象的狀態(tài),所以一般是重載為成員函數(shù)
        • 重載遞增遞減,一定要和指針的遞增遞減區(qū)分開。因為這里的重載操作的是對象,而不是指針(由于指針是內(nèi)置類型,指針的遞增遞減是無法重載的),所以一般情況的遞增遞減是操作對象內(nèi)部的成員變量。
        • 遞增和遞減分為前置和后置情況,a = ++b;(前置), a = b++;(后置)。因為符號一樣,所以給后置版本加一個int形參作為區(qū)分,這個形參是0,但是在函數(shù)體中是用不到的,只是為了區(qū)分前置后置。例如:
              // ++與--運(yùn)算符重載注意的點(diǎn)
              class CA{
                  public:
                      int pos;
                      // 前置++就是增加當(dāng)前對象的pos的值,并返回當(dāng)前對象
                      CA operator++(){
                          pos++;
                          return *this;
                      }
                      // 后置++就是增加當(dāng)前對象的pos的值,并返回增加pos之前的對象
                      CA operator++(int){
                          CA temp = *this;
                          ++*this;
                          return temp;
                      }
              };
              CA ca,cb;
              ca.pos = 1;
              cb = ca++;
              cout << "cb = " << cb.pos << endl;
              cb = ++ca;
              cout << "cb = " << cb.pos << endl;
          
    • 一元減運(yùn)算符,即負(fù)號(-)
          // 重載一元減運(yùn)算符-
          class Distance{
              private:
                  int feet;
                  int inches;
              public:
                  Distance(){
                      feet = 0;
                      inches = 0;
                  }
                  Distance(int f, int i): feet(f), inches(i){
                      cout << "Distance類對象的構(gòu)造函數(shù)\n";
                  }
                  void displayDistance(){
                      cout << "F = " << feet << " I = " << inches << endl;
                  }
                  // 重載運(yùn)算符-
                  Distance operator-(){
                      feet = -feet;
                      inches = -inches;
                      return Distance(feet, inches);
                  }
              };
          Distance D1(10, 11), D2(-5, 11);
          -D1;
          D1.displayDistance();
          -D2;
          D2.displayDistance();
      
    • 邏輯非運(yùn)算符(!)

5.2 二元運(yùn)算符重載

  • 二元運(yùn)算符需要兩個參數(shù),下面是二元運(yùn)算符的實例。我們平常使用的加運(yùn)算符( + )、減運(yùn)算符( - )、乘運(yùn)算符( * )和除運(yùn)算符( / )都屬于二元運(yùn)算符。就像加(+)運(yùn)算符。
        class Box{
            public:
                double getVolume(){
                    return length * width * height;
                }
                void setLength(int len){
                    length = len;
                }
                void setWidth(int wid){
                    width = wid;
                }
                void setHeight(int hei){
                    height = hei;
                }
            // 運(yùn)算符重載:用于把兩個box對象相加
                Box operator+(const Box& b){
                    Box box;
                    box.length = this->length + b.length;
                    box.width = this->width + b.width;
                    box.height = this->height + b.height;
                    return box;
                }
            private:
                int length;
                int width;
                int height;
        };
    
        int main(){
            Box box1;
            Box box2;
            Box box3;
            double volume = 0.0;
            box1.setLength(6.0);
            box1.setWidth(7.0);
            box1.setHeight(5.0);
    
            box2.setLength(12.0);
            box2.setWidth(13.0);
            box2.setHeight(10.0);
    
            volume = box1.getVolume();
            cout << "box1的體積是: " << volume << endl;
            volume = box2.getVolume();
            cout << "box2的體積是: " << volume << endl;
    
            box3 = box1 + box2;
            volume = box3.getVolume();
            cout << "box3的體積是: " << volume << endl;
            cout << "----------------------------------------------\n";
            return 0;
        }
    

5.3 關(guān)系運(yùn)算符重載

  • C++ 語言支持各種關(guān)系運(yùn)算符( < 、 > 、 <= 、 >= 、 == 等等),它們可用于比較 C++ 內(nèi)置的數(shù)據(jù)類型,可以重載任何一個關(guān)系運(yùn)算符,重載后的關(guān)系運(yùn)算符可用于比較類的對象。
        class Distance{
            private:
                int feet;
                int inches;
            public:
                Distance(){
                    feet = 0;
                    inches = 0;
                }
                Distance(int f, int i): feet(f), inches(i){
                    cout << "Distance類對象的構(gòu)造函數(shù)\n";
                }
                void displayDistance(){
                    cout << "F = " << feet << " I = " << inches << endl;
                }
                // 重載關(guān)系運(yùn)算符<
                bool operator < (const Distance& d){
                    if(feet < d.feet)
                        return true;
                    if(feet == d.feet && inches < d.inches)
                        return true;
                    return false;
                }     
        };
        if (D1 < D2)
            cout << "D1 < D2\n";
        else    
            cout << "D1 > D2\n";
    

5.4 輸入輸出運(yùn)算符重載

  • C++ 能夠使用流提取運(yùn)算符>>和流插入運(yùn)算符<<來輸入和輸出內(nèi)置的數(shù)據(jù)類型??梢灾剌d流提取運(yùn)算符和流插入運(yùn)算符來操作對象等用戶自定義的數(shù)據(jù)類型。需要把運(yùn)算符重載函數(shù)聲明為類的友元函數(shù),這樣我們就能不用創(chuàng)建對象而直接調(diào)用函數(shù)。
        class Distance{
            private:
                int feet;
                int inches;
            public:
                Distance(){
                    feet = 0;
                    inches = 0;
                }
                Distance(int f, int i): feet(f), inches(i){
                    cout << "Distance類對象的構(gòu)造函數(shù)\n";
                }
                void displayDistance(){
                    cout << "F = " << feet << " I = " << inches << endl;
                }
                // 重載輸入輸出運(yùn)算符
                friend ostream &operator<<(ostream &output, const Distance& D){
                    output << "F = " << D.feet << " I = " << D.inches << endl;
                    return output;
                }
                friend istream &operator>>(istream &input, Distance &D){
                    input >> D.feet >> D.inches;
                    return input;
                }
        };
        Distance D3(11, 10), D4(3, 2), D5;
        cout << "請輸入目標(biāo)值D5 = ";
        cin >> D5;
        cout << "D3 = " << D3 << endl;
        cout << "D4 = " << D4 << endl;
        cout << "D5 = " << D5 << endl;
    

5.5 賦值運(yùn)算符重載

  • 像其他運(yùn)算符一樣,您可以重載賦值運(yùn)算符( = ),用于創(chuàng)建一個對象,比如拷貝構(gòu)造函數(shù)。
        class Distance{
        private:
            int feet;
            int inches;
        public:
            Distance(){
                feet = 0;
                inches = 0;
            }
            Distance(int f, int i): feet(f), inches(i){
                cout << "Distance類對象的構(gòu)造函數(shù)\n";
            }
            void displayDistance(){
                cout << "F = " << feet << " I = " << inches << endl;
            }
            // 賦值運(yùn)算符重載
            void operator=(const Distance& D){
                feet = D.feet;
                inches = D.inches;
            }
        };
        D1 = D2;
        cout << "D1: " << D1 << endl;
        D1.displayDistance();
    
  • 當(dāng)用用戶自定義類型變量向內(nèi)置類型變量賦值時,可以使用自定義類型的隱式轉(zhuǎn)換
        class Int{
        private:
            int n;
        public:
            Int(int i){
                cout << "Int對象的構(gòu)造函數(shù)\n";
            };
            operator int(){  // 這里就是隱式轉(zhuǎn)換聲明,應(yīng)注意到它與運(yùn)算符重載的不同之處
                return n;
            }
        };
        Int int_obj(3);
        int i = int_obj;  // 隱式調(diào)用轉(zhuǎn)換函數(shù)
        cout << "i = " << i << endl;
        cout << "int_obj = " << int_obj << endl;  // 由于未重載Int的<<操作符,將隱式調(diào)用轉(zhuǎn)換函數(shù)
    

5.6 函數(shù)調(diào)用運(yùn)算符重載()

  • 函數(shù)調(diào)用運(yùn)算符()可以被重載用于類的對象。當(dāng)重載()時,不是創(chuàng)造了一種新的調(diào)用函數(shù)的方式。相反地,這是創(chuàng)建一個可以傳遞任意數(shù)目參數(shù)的運(yùn)算符函數(shù)。
        class Distance{
        private:
            int feet;
            int inches;
        public:
            Distance(){
                feet = 0;
                inches = 0;
            }
            Distance(int f, int i): feet(f), inches(i){
                cout << "Distance類對象的構(gòu)造函數(shù)\n";
            }
            void displayDistance(){
                cout << "F = " << feet << " I = " << inches << endl;
            }
            // 重載函數(shù)調(diào)用運(yùn)算符
            Distance operator()(int a, int b, int c){
                Distance D;
                // 進(jìn)行隨機(jī)計算
                D.feet = a + c + 10;
                D.inches = b + c + 100;
                return D;
            }
        };
        Distance D6;
        D6 = D1(10, 10, 10);
        cout << "D6: " << D6 << endl;
    

5.7 下標(biāo)運(yùn)算符重載[]

  • 下標(biāo)操作符[]通常用于訪問數(shù)組元素,重載該運(yùn)算符用于增強(qiáng)操作C++數(shù)組的功能
        // 下標(biāo)運(yùn)算符重載
        const int SIZE = 10;
        class safearray{
            private:
                int arr[SIZE];
            public:
                safearray(){
                    register int i;
                    for(i = 0; i < SIZE; i++)
                        arr[i] = i;
                }
                // 下標(biāo)運(yùn)算符重載
                int & operator[](int i){
                    if(i > SIZE){
                        cout << "索引超過最大值: ";
                        return arr[0];
                    }
                    return arr[i];
                }      
        };
        safearray sa;
        cout << "sa[2] = " << sa[2] << endl;
        cout << "sa[5] = " << sa[5] << endl;
        cout << "sa[12] = " << sa[12] << endl;
    

5.8 類成員訪問運(yùn)算符->重載

  • 類成員訪問運(yùn)算符->可以被重載,但它較為麻煩。它被定義用于為一個類賦予"指針"行為。運(yùn)算符->必須是一個成員函數(shù)。如果使用了->運(yùn)算符,返回類型必須是指針或者是類的對象。運(yùn)算符->通常與指針引用運(yùn)算符*結(jié)合使用,用于實現(xiàn)"智能指針"的功能。這些指針是行為與正常指針相似的對象,唯一不同的是,當(dāng)通過指針訪問對象時,它們會執(zhí)行其他的任務(wù)。比如,當(dāng)指針銷毀時,或者當(dāng)指針指向另一個對象時,會自動刪除對象。
        // 類成員訪問運(yùn)算符->
        class OO{
            static int i,j;
            public:
                void f() const{  // 常函數(shù)
                    cout << i++ << endl;
                }
                void g() const{
                    cout << j++ << endl;
                }
        };
        // 靜態(tài)成員定義
        int OO::i = 10;
        int OO::j = 12;
        // 為上面的類實現(xiàn)一個容器
        class ObjContainer {
        vector<OO*> a;
        public:
        void add(OO* obj)
        { 
            a.push_back(obj);  // 調(diào)用向量的標(biāo)準(zhǔn)方法
        }
        friend class SmartPointer;
        };
        // 實現(xiàn)智能指針,用于訪問類 Obj 的成員
        class SmartPointer {
        ObjContainer oc;
        int index;
        public:
        SmartPointer(ObjContainer& objc)
        { 
            oc = objc;
            index = 0;
        }
        // 返回值表示列表結(jié)束
        bool operator++() // 前綴版本
        { 
            if(index >= oc.a.size() - 1) return false;
            if(oc.a[++index] == 0) return false;
            return true;
        }
        bool operator++(int) // 后綴版本
        { 
            return operator++();
        }
        // 重載運(yùn)算符 ->
        OO* operator->() const 
        {
            if(!oc.a[index])
            {
                cout << "Zero value";
                return (OO*)0;
            }
            return oc.a[index];
        }
        };
        const int sz = 10;
        OO o[sz];
        ObjContainer oc;
        for(int i = 0; i < sz; i++)
        {
            oc.add(&o[i]);
        }
        SmartPointer sp(oc); // 創(chuàng)建一個迭代器
        do {
            sp->f(); // 智能指針調(diào)用
            sp->g();
        } while(sp++);
    

6.運(yùn)算符重載注意的點(diǎn)

  • a.運(yùn)算重載符不可以改變語法結(jié)構(gòu)
  • b.運(yùn)算重載符不可以改變操作數(shù)的個數(shù)
  • c.運(yùn)算重載符不可以改變優(yōu)先級
  • d.運(yùn)算重載符不可以改變結(jié)合性

7.重載、覆蓋、隱藏(重定義)的區(qū)別:

  • 重載:指的是函數(shù)具有的不同的參數(shù)列表,而函數(shù)名相同的函數(shù)。重載要求參數(shù)列表必須不同,比如參數(shù)的類型不同、參數(shù)的個數(shù)不同、參數(shù)的順序不同。如果僅僅是函數(shù)的返回值不同是沒辦法重載的,因為重載要求參數(shù)列表必須不同。(發(fā)生在同一個類里)
  • 覆蓋:存在類中,子類重寫從基類繼承過來的函數(shù)。被重寫的函數(shù)不能是static的。必須是virtual的。但是函數(shù)名、返回值、參數(shù)列表都必須和基類相同。(發(fā)生在基類和子類)
  • 隱藏:子類重新定義父類中有相同名稱的非虛函數(shù)(參數(shù)列表可以不同)。(發(fā)生在基類和子類)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容