上一節中雞啄米講到了運算符重載的概念和規則,運算符可以重載為類的成員函數或友元函數,這一節就來講講運算符怎樣重載為類的成員函數。

       運算符重載為類的成員函數后就可以像其他成員函數一樣訪問本類的數據成員了。在類的外部通過類的對象,可以像原運算符的使用方式那樣使用重載的運算符,比如,“+”運算符被重載為類A的成員函數后,A的對象a和其他對象b就可以這樣進行加法運算:a+b。

       重載的運算符可能是雙目運算符也可能是單目運算符

       如果是雙目運算符,比如“+”和“-”,則一個操作數是使用此運算符的對象本身,另一個操作數使用運算符重載函數傳遞進來的對象。假設有雙目運算符U,a為類A的對象,另有某類也可以是A類的對象b,我們想實現a U b這樣的運算,就可以把U重載為類A的成員函數,此函數只有一個形參,形參的類型為對象b的類型。這樣進行a U b的運算就相當于函數調用:a.operator U(b)。

       如果是單目運算符,比如“++”和“--”,操作數就是此對象本身,重載函數不需要傳遞參數,只是后置單目運算符語法上規定有一個形式上的參數,以區別于前置單目運算符。

       假設有前置單目運算符U,如前置“++”,a為類A的對象,我們想實現U a這樣的運算,也可以把U重載為類A的成員函數,此函數沒有形參。這樣U a表達式就相當于函數調用:a.operator U()。

       假設有后置單目運算符U,如后置“--”,a為類A的對象,我們想實現a U這樣的運算,同樣可以把U重載為類A的成員函數,但此函數需要有一個整型的形參。重載后a U表達式就相當于函數調用:a.operator U(0)。

       這里雞啄米需要強調下,前置單目運算符重載和后置單目運算符重載在語法形式上的區別就是前者重載函數沒有形參,而后者重載函數有一個整型形參,此形參對函數體沒有任何影響,這只是語法上的規定,僅僅是為了區分前置和后置

       雞啄米給大家兩個程序例子,分別演示雙目運算符和單目運算符的使用。

       第一個例子:時間值的加法,比如2個小時20分鐘加3個小時30分鐘,應該是5個小時50分鐘,運算規則就是小時數相加,分鐘數相加,如果分鐘數的和超過60分鐘則小時數再加1,分鐘數減60。雙目運算符“+”需要重載為時間值類的成員函數,此函數只有一個形參,類型也是時間值類的對象。

       #include <iostream>
       using namespace std;
       class CTimeSpan
       {
       public:
                   CTimeSpan(int nHours=0, int nMins=0);      // 構造函數
                   CTimeSpan operator +(CTimeSpan ts);        // 運算符“+”重載為成員函數
                   int GetHours()      { return m_nHours; }   // 獲取小時數
                   int GetMins()       { return m_nMins; }    // 獲取分鐘數
                   void Show();                               // 顯示時間值
       private:
                   int m_nHours;       // 小時數
                   int m_nMins;        // 分鐘數
       };
       CTimeSpan::CTimeSpan(int nHours, int nMins)          // 構造函數的實現
       {
                  nHours += nMins/60;
                  nMins %= 60;
                  m_nHours = nHours;
                  m_nMins = nMins;
       }
       CTimeSpan CTimeSpan::operator +(CTimeSpan ts)    // 重載運算符函數實現
       {
                  int nNewHours;
                  int nNewMins;
                  nNewHours = m_nHours + ts.GetHours();
                  nNewMins = m_nMins + ts.GetMins();
                  nNewHours += nNewMins/60;
                  nNewMins %= 60;
                  return CTimeSpan(nNewHours, nNewMins);
       }
       void CTimeSpan::Show()
       {
                 cout << m_nHours << "小時" << m_nMins << "分鐘" << endl;
       }
       int main()
       {
                 CTimeSpan timeSpan1(2, 50);
                 CTimeSpan timeSpan2(3, 30);
                 CTimeSpan timeSum;
                 timeSum = timeSpan1 + timeSpan2;
                 cout << "timeSpan1: ";
                 timeSpan1.Show();
                 cout << "timeSpan2: ";
                 timeSpan2.Show();
                 timeSum = timeSpan1 + timeSpan2;
                 cout << "timeSum=timeSpan1+timeSpan2: ";
                 timeSum.Show();
                 return 0;
       }

雞啄米:C++編程入門系列之四十六(多態性:運算符重載為成員函數)

       程序運行結果:

       timeSpan1: 2小時50分鐘
       timeSpan2: 3小時30分鐘
       timeSum=timeSpan1+timeSpan2: 6小時20分鐘

       我們可以看出,運算符重載成員函數跟一般的成員函數類似,只是使用了關鍵字operator。使用重載運算符的方式與原運算符相同。運算符作用于整型、浮點型和CTimeSpan等不同的對象會發生不同的操作行為,這就是多態性。

       注意,重載“+”的函數中,語句return CTimeSpan(nNewHours, nNewMins);看似是對CTimeSpan構造函數的調用,實則不然,這是構造一個臨時對象并將它返回到主函數中。

       第二個例子:時鐘類的例子。前置“++”和后置“++”重載為時鐘類的成員函數。前置“++”重載函數沒有形參,后置“++”重載函數有一個整型形參。

        #include<iostream>
        using namespace std;
        class Clock //時鐘類聲明
        {
        public: //外部接口
                     Clock(int NewH=0, int NewM=0, int NewS=0);
                     void ShowTime();
                     Clock&  operator ++();  //前置單目運算符重載
                     Clock operator ++(int);  //后置單目運算符重載
        private: //私有數據成員
                     int Hour,Minute,Second;
        };
       Clock::Clock(int NewH, int NewM, int NewS)
       {
                     if (0<=NewH && NewH<24 && 0<=NewM && NewM<60 && 0<= NewS && NewS<60)
                     {
                                  Hour = NewH;
                                  Minute = NewM;
                                  Second = NewS;
                     }
                     else
                                  cout << "錯誤的時間!" << endl;
       }
       void Clock::ShowTime()
       {
                    cout << Hour << ":" << Minute << ":" << Second << endl;
       }
      Clock& Clock::operator ++() //前置單目運算符重載函數
      { 
                    Second++;
                    if(Second>=60)
                    {   
                               Second=Second-60;
                               Minute++;
                               if(Minute>=60)
                               {
                                         Minute=Minute-60;
                                         Hour++;
                                         Hour=Hour%24;
                               }
                     }
                     return *this;
       }
       //后置單目運算符重載
       Clock Clock::operator ++(int)      //注意形參表中的整型參數 
       {    
                    Clock old=*this;
                    ++(*this);
                    return old;
       }
       int main()
       {
                   Clock myClock(23,59,59);
                   cout<<"初始時間myClock:";
                   myClock.ShowTime();
                   cout<<"myClock++:";
                   (myClock++).ShowTime();
                   cout<<"++myClock:";
                   (++myClock).ShowTime();
                   return 0;
       }

       程序運行結果:

       初始時間myClock:23:59:59
       myClock++:23:59:59
       ++myClock:0:0:1

       因為后置單目運算符重載函數中的整型形參沒有實際意義,只是為了區分前置和后置,所以參數表中只給出類型就行了,參數名寫不寫都可以。

       運算符重載部分需要大家認真理解,可以在VS2010上運行上面兩個例子,然后自己舉一反三,寫幾個簡單例子試驗下其他運算符。

       雞啄米就講到這了,有問題歡迎在雞啄米博客交流。謝謝大家。

 

除非特別注明,雞啄米文章均為原創
轉載請標明本文地址:http://www.cpbsu.com/software/115.html
2012年1月10日
作者:雞啄米 分類:軟件開發 瀏覽: 評論:22