【C++】運算符重載 二 (實例)

前接文章:【C++】運算符重載 一

值得注意的是:

  • 1、運算重載符不可以改變語法結構。
  • 2、運算重載符不可以改變操作數的個數。
  • 3、運算重載符不可以改變優先級。
  • 4、運算重載符不可以改變結合性。
  •  

類重載、覆蓋、重定義之間的區別:

重載指的是函數具有的不同的參數列表,而函數名相同的函數。重載要求參數列表必須不同,比如參數的類型不同、參數的個數不同、參數的順序不同。如果僅僅是函數的返回值不同是沒辦法重載的,因爲重載要求參數列表必須不同。(發生在同一個類裏)

 覆蓋是存在類中,子類重寫從基類繼承過來的函數。被重寫的函數不能是static的。必須是virtual的。但是函數名、返回值、參數列表都必須和基類相同(發生在基類和子類)

 重定義也叫做隱藏,子類重新定義父類中有相同名稱的非虛函數 ( 參數列表可以不同 ) 。(發生在基類和子類)


運算符重載實例

下面提供了各種運算符重載的實例,幫助您更好地理解重載的概念。


C++ 一元運算符重載

一元運算符只對一個操作數進行操作,下面是一元運算符的實例:

  • 遞增運算符( ++ )和遞減運算符( -- )是 C++ 語言中兩個重要的一元運算符。下面的實例演示瞭如何重載遞增運算符( ++ ),包括前綴和後綴兩種用法。類似地,您也可以嘗試重載遞減運算符( -- )。一元運算符通常出現在它們所操作的對象的左邊,比如 !obj、-obj 和 ++obj,但有時它們也可以作爲後綴,比如 obj++ 或 obj--。
#include <iostream>
using namespace std;

class Time
{
private:
	int hours;             // 0 到 23
	int minutes;           // 0 到 59
public:
	// 所需的構造函數
	Time() {
		hours = 0;
		minutes = 0;
	}
	Time(int h, int m) {
		hours = h;
		minutes = m;
	}
	// 顯示時間的方法
	void displayTime()
	{
		cout << "H: " << hours << " M:" << minutes << endl;
	}

	// 重載前綴遞增運算符( ++ )
	Time operator++ ()
	{
		++minutes;          // 對象加 1
		if (minutes >= 60)
		{
			++hours;
			minutes -= 60;
		}
		return Time(hours, minutes);
	}

	// 重載後綴遞增運算符( ++ )
	Time operator++(int)
	{
		// 保存原始值
		Time T(hours, minutes);
		// 對象加 1
		++minutes;
		if (minutes >= 60)
		{
			++hours;
			minutes -= 60;
		}
		// 返回舊的原始值
		return T;
	}
};

int main()
{
	Time T1(11, 59), T2(10, 40);

	++T1;                    // T1 加 1
	T1.displayTime();        // 顯示 T1
	++T1;                    // T1 再加 1
	T1.displayTime();        // 顯示 T1

	T2++;                    // T2 加 1
	T2.displayTime();        // 顯示 T2
	T2++;                    // T2 再加 1
	T2.displayTime();        // 顯示 T2
	return 0;
}

--------------------------------------------------
H: 12 M:0
H: 12 M:1
H: 10 M:41
H: 10 M:42
--------------------------------------------------

注意前綴和後綴的寫法!!!

  • 一元減運算符,即負號( - )
#include <iostream>
using namespace std;

class Distance
{
private:
	int feet;             // 0 到無窮
	int inches;           // 0 到 12
public:
	// 所需的構造函數
	Distance() {
		feet = 0;
		inches = 0;
	}
	Distance(int f, int i) {
		feet = f;
		inches = i;
	}
	// 顯示距離的方法
	void displayDistance()
	{
		cout << "F: " << feet << " I:" << inches << endl;
	}

	// 重載負運算符( - )
	Distance operator- ()
	{
		feet = -feet;
		inches = -inches;
		return Distance(feet, inches);
	}
};

int main()
{
	Distance D1(11, 10), D2(-5, 11);

	-D1;                     // 取相反數
	D1.displayDistance();    // 距離 D1

	-D2;                     // 取相反數
	D2.displayDistance();    // 距離 D2

	return 0;
}

-----------------------------------------------
F: -11 I:-10
F: 5 I:-11
-----------------------------------------------
  • 希望上面的實例能夠幫您更好地理解一元運算符重載的概念,類似地,您可以嘗試重載邏輯非運算符( ! )。

C++ 二元運算符重載

二元運算符需要兩個參數,下面是二元運算符的實例。我們平常使用的加運算符( + )、減運算符( - )、乘運算符( * )和除運算符( / )都屬於二元運算符。就像加(+)運算符。下面的實例演示瞭如何重載加運算符( + )。類似地,您也可以嘗試重載減運算符( - )和除運算符( / )。

#include <iostream>
using namespace std;
 
class Box
{
   double length;      // 長度
   double breadth;     // 寬度
   double height;      // 高度
public:
 
   double getVolume(void)
   {
      return length * breadth * height;
   }
   void setLength( double len )
   {
       length = len;
   }
 
   void setBreadth( double bre )
   {
       breadth = bre;
   }
 
   void setHeight( double hei )
   {
       height = hei;
   }
   // 重載 + 運算符,用於把兩個 Box 對象相加
   Box operator+(const Box& b)
   {
      Box box;
      box.length = this->length + b.length;
      box.breadth = this->breadth + b.breadth;
      box.height = this->height + b.height;
      return box;
   }
};
// 程序的主函數
int main( )
{
   Box Box1;                // 聲明 Box1,類型爲 Box
   Box Box2;                // 聲明 Box2,類型爲 Box
   Box Box3;                // 聲明 Box3,類型爲 Box
   double volume = 0.0;     // 把體積存儲在該變量中
 
   // Box1 詳述
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // Box2 詳述
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // Box1 的體積
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // Box2 的體積
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;
 
   // 把兩個對象相加,得到 Box3
   Box3 = Box1 + Box2;
 
   // Box3 的體積
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;
 
   return 0;
}

-----------------------------------
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400
-----------------------------------

C++ 關係運算符重載

C++ 語言支持各種關係運算符( < 、 > 、 <= 、 >= 、 == 等等),它們可用於比較 C++ 內置的數據類型。您可以重載任何一個關係運算符,重載後的關係運算符可用於比較類的對象。下面的實例演示瞭如何重載 < 運算符,類似地,您也可以嘗試重載其他的關係運算符。

#include <iostream>
using namespace std;
 
class Distance
{
   private:
      int feet;             // 0 到無窮
      int inches;           // 0 到 12
   public:
      // 所需的構造函數
      Distance(){
         feet = 0;
         inches = 0;
      }
      Distance(int f, int i){
         feet = f;
         inches = i;
      }
      // 顯示距離的方法
      void displayDistance()
      {
         cout << "F: " << feet << " I:" << inches <<endl;
      }
      // 重載負運算符( - )
      Distance operator- ()  
      {
         feet = -feet;
         inches = -inches;
         return Distance(feet, inches);
      }
      // 重載小於運算符( < )
      bool operator <(const Distance& d)
      {
         if(feet < d.feet)
         {
            return true;
         }
         if(feet == d.feet && inches < d.inches)
         {
            return true;
         }
         return false;
      }
};

int main()
{
   Distance D1(11, 10), D2(5, 11);
 
   if( D1 < D2 )
   {
      cout << "D1 is less than D2 " << endl;
   }
   else
   {
      cout << "D2 is less than D1 " << endl;
   }
   return 0;
}


-----------------------------
D2 is less than D1
-----------------------------

C++ 輸入/輸出運算符重載

C++ 能夠使用流提取運算符 >> 和流插入運算符 << 來輸入和輸出內置的數據類型。您可以重載流提取運算符和流插入運算符來操作對象等用戶自定義的數據類型。在這裏,有一點很重要,我們需要把運算符重載函數聲明爲類的友元函數,這樣我們就能不用創建對象而直接調用函數。下面的實例演示瞭如何重載提取運算符 >> 和插入運算符 <<。

#include <iostream>
using namespace std;

class Distance
{
private:
	int feet;             // 0 到無窮
	int inches;           // 0 到 12
public:
	// 所需的構造函數
	Distance() 
	{
		feet = 0;
		inches = 0;
	}
	Distance(int f, int i) 
	{
		feet = f;
		inches = i;
	}

	friend ostream &operator<<(ostream &output,	const Distance &D)
	{
		output << "F : " << D.feet << " I : " << D.inches;
		return output;
	}
	friend istream &operator >> (istream  &input, Distance &D)
	{
		input >> D.feet >> D.inches;
		return input;
	}
};

int main()
{
	Distance D1(11, 10), D2(5, 11), D3;

	cout << "Enter the value of object : " << endl;
	cin >> D3;
	cout << "First Distance : " << D1 << endl;
	cout << "Second Distance :" << D2 << endl;
	cout << "Third Distance :" << D3 << endl;

	return 0;
}

----------------------
Enter the value of object :
70
10
First Distance : F : 11 I : 10
Second Distance :F : 5 I : 11
Third Distance :F : 70 I : 10
----------------------

C++ 賦值運算符重載

就像其他運算符一樣,您可以重載賦值運算符( = ),用於創建一個對象,比如拷貝構造函數。下面的實例演示瞭如何重載賦值運算符。

#include <iostream>
using namespace std;
 
class Distance
{
   private:
      int feet;             // 0 到無窮
      int inches;           // 0 到 12
   public:
      // 所需的構造函數
      Distance(){
         feet = 0;
         inches = 0;
      }
      Distance(int f, int i){
         feet = f;
         inches = i;
      }
      void operator=(const Distance &D )
      { 
         feet = D.feet;
         inches = D.inches;
      }
      // 顯示距離的方法
      void displayDistance()
      {
         cout << "F: " << feet <<  " I:" <<  inches << endl;
      }
      
};
int main()
{
   Distance D1(11, 10), D2(5, 11);
 
   cout << "First Distance : "; 
   D1.displayDistance();
   cout << "Second Distance :"; 
   D2.displayDistance();
 
   // 使用賦值運算符
   D1 = D2;
   cout << "First Distance :"; 
   D1.displayDistance();
 
   return 0;
}

----------------------------
First Distance : F: 11 I:10
Second Distance :F: 5 I:11
First Distance :F: 5 I:11
----------------------------

C++ 函數調用運算符 () 重載

函數調用運算符 () 可以被重載用於類的對象。當重載 () 時,您不是創造了一種新的調用函數的方式,相反地,這是創建一個可以傳遞任意數目參數的運算符函數。下面的實例演示瞭如何重載函數調用運算符 ()。

#include <iostream>
using namespace std;
 
class Distance
{
   private:
      int feet;             // 0 到無窮
      int inches;           // 0 到 12
   public:
      // 所需的構造函數
      Distance(){
         feet = 0;
         inches = 0;
      }
      Distance(int f, int i){
         feet = f;
         inches = i;
      }
      // 重載函數調用運算符
      Distance operator()(int a, int b, int c)
      {
         Distance D;
         // 進行隨機計算
         D.feet = a + c + 10;
         D.inches = b + c + 100 ;
         return D;
      }
      // 顯示距離的方法
      void displayDistance()
      {
         cout << "F: " << feet <<  " I:" <<  inches << endl;
      }
      
};
int main()
{
   Distance D1(11, 10), D2;

   cout << "First Distance : "; 
   D1.displayDistance();

   D2 = D1(10, 10, 10); // invoke operator()
   cout << "Second Distance :"; 
   D2.displayDistance();

   return 0;
}
-----------------------------------------
First Distance : F: 11 I:10
Second Distance :F: 30 I:120
-----------------------------------------

C++ 下標運算符 [] 重載

下標操作符 [] 通常用於訪問數組元素。重載該運算符用於增強操作 C++ 數組的功能。下面的實例演示瞭如何重載下標運算符 []。

#include <iostream>
using namespace std;
const int SIZE = 10;

class safearay
{
   private:
      int arr[SIZE];
   public:
      safearay() 
      {
         register int i;
         for(i = 0; i < SIZE; i++)
         {
           arr[i] = i;
         }
      }
      int& operator[](int i)
      {
          if( i > SIZE )
          {
              cout << "索引超過最大值" <<endl; 
              // 返回第一個元素
              return arr[0];
          }
          return arr[i];
      }
};
int main()
{
   safearay A;

   cout << "A[2] 的值爲 : " << A[2] <<endl;
   cout << "A[5] 的值爲 : " << A[5]<<endl;
   cout << "A[12] 的值爲 : " << A[12]<<endl;

   return 0;
}
-----------------------
A[2] 的值爲 : 2
A[5] 的值爲 : 5
A[12] 的值爲 : 索引超過最大值
0
-----------------------

C++ 類成員訪問運算符 -> 重載

類成員訪問運算符( -> )可以被重載,但它較爲麻煩。它被定義用於爲一個類賦予"指針"行爲。運算符 -> 必須是一個成員函數。如果使用了 -> 運算符,返回類型必須是指針或者是類的對象。運算符 -> 通常與指針引用運算符 * 結合使用,用於實現"智能指針"的功能。這些指針是行爲與正常指針相似的對象,唯一不同的是,當您通過指針訪問對象時,它們會執行其他的任務。比如,當指針銷燬時,或者當指針指向另一個對象時,會自動刪除對象。間接引用運算符 -> 可被定義爲一個一元后綴運算符。也就是說,給出一個類:

class Ptr{
   //...
   X * operator->();
};

類 Ptr 的對象可用於訪問類 X 的成員,使用方式與指針的用法十分相似。例如:

void f(Ptr p )
{
   p->m = 10 ; // (p.operator->())->m = 10
}

語句 p->m 被解釋爲 (p.operator->())->m。同樣地,下面的實例演示瞭如何重載類成員訪問運算符 ->。

#include <iostream>
#include <vector>
using namespace std;
 
// 假設一個實際的類
class Obj {
   static int i, j;
public:
   void f() const { cout << i++ << endl; }
   void g() const { cout << j++ << endl; }
};
 
// 靜態成員定義
int Obj::i = 10;
int Obj::j = 12;
 
// 爲上面的類實現一個容器
class ObjContainer {
   vector<Obj*> a;
public:
   void add(Obj* obj)
   { 
      a.push_back(obj);  // 調用向量的標準方法
   }
   friend class SmartPointer;
};
 
// 實現智能指針,用於訪問類 Obj 的成員
class SmartPointer {
   ObjContainer oc;
   int index;
public:
   SmartPointer(ObjContainer& objc)
   { 
       oc = objc;
       index = 0;
   }
   // 返回值表示列表結束
   bool operator++() // 前綴版本
   { 
     if(index >= oc.a.size() - 1) return false;
     if(oc.a[++index] == 0) return false;
     return true;
   }
   bool operator++(int) // 後綴版本
   { 
      return operator++();
   }
   // 重載運算符 ->
   Obj* operator->() const 
   {
     if(!oc.a[index])
     {
        cout << "Zero value";
        return (Obj*)0;
     }
     return oc.a[index];
   }
};
 
int main() {
   const int sz = 10;
   Obj o[sz];
   ObjContainer oc;
   for(int i = 0; i < sz; i++)
   {
       oc.add(&o[i]);
   }
   SmartPointer sp(oc); // 創建一個迭代器
   do {
      sp->f(); // 智能指針調用
      sp->g();
   } while(sp++);
   return 0;
}
------------------------------------------------------
10
12
11
13
12
14
13
15
14
16
15
17
16
18
17
19
18
20
19
21
------------------------------------------------------

參考來源:C++ 重載運算符和重載函數

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章