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

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

下面的實例演示瞭如何重載函數調用運算符 ()。

#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

2、

總結:

  需要以類成員函數的形式對函數調用操作符“()”進行重載。

  只有常成員函數才能處理常對象,故我們依然在類中提供兩個版本的函數調用操作符重載函數。若調用對象爲常對象(const),則必須用常函數。  

  這裏面的關於在函數中拋出異常,在調用處捕捉異常,值得參考學習。

 

與下標操作符重載函數相同,我們同樣需要以類成員函數的形式對函數調用操作符“()”進行重載。其聲明語法只有一種形式:
    返回類型 operator()( 參數列表 );

例1:
複製代碼
#include<iostream>
#include<string>
using namespace std;

class Array
{
public:
    Array(){len1 = 0; len2 = 0; num = NULL; };
    Array(int m, int n);
    int & operator()(int, int);
    const int & operator()(int, int)const;
    int getlen1()const {return len1;}
    int getlen2()const {return len2;}
private:
    int len1;
    int len2;
    int * num;
};

Array::Array(int m, int n)
{
    int size = m * n;
    try
    {
        num = new int[size];
    }
    catch(bad_alloc)
    {
        cerr<<"allocate storage failure!"<<endl;
        throw;
    }
    len1 = m;
    len2 = n;
}

int & Array::operator()(int i, int j)
{
    if(i < 0 || i >= len1)
        throw string("1 out of bounds!");
    if(j < 0 || j >= len2)
        throw string("2 out of bounds!");
    return num[ i*len2 + j ];
}

const int & Array::operator()(int i, int j)const
{
    if(i < 0 || i >= len1)
        throw string("1 out of bounds!");
    if(j < 0 || j >= len2)
        throw string("2 out of bounds!");
    return num[ i*len2 + j ];
}

int main()
{
    Array A(3,4);
    int i,j;
    for(i = 0; i < A.getlen1(); i++)
        for(j = 0; j < A.getlen2(); j++)
            A(i,j) = i * A.getlen2() + j;
    for(i = 0; i < A.getlen1(); i++)
        for(j = 0; j < A.getlen2(); j++)
            cout<< A(i,j)<<" ";
    cout<<endl;
    try
    {
        cout<< A(5, 3) << endl;
    }
    catch(string s)
    {
        cerr<< s <<endl;
    }
    try
    {
        cout<< A(2, 6) << endl;
    }
    catch(string s)
    {
        cerr<< s <<endl;
    }
    return 0;
}
複製代碼

 

在這個例子中我們定義了一個Array類,這個類描述的是一個二維的數組,在類中我們先定義了一個默認構造函數,之後聲明瞭一個帶參數的構造函數“Array(int m, int n);”,所帶的這兩個參數分別是數組的兩個維度的大小。之後聲明瞭一個函數調用操作符重載函數“int & operator()(int, int);”和“const int & operator()(int, int)const;”,同樣的,因爲只有常成員函數才能處理常對象,故我們依然在類中提供兩個版本的函數調用操作符重載函數。我們可以去看一下兩個函數的函數定義,在它們的函數體中,我們先是做一個越界檢測,當然對於二維數組而言,邊界是有兩個的,因此有兩次邊界檢測的。如果沒有越界則會返回對應的值。有了這兩個函數調用操作符重載函數,我們就可以用A(i,j)的形式訪問二維數組中的數據了。

當我們用A(i,j)的形式訪問二維數組中的數據時,A(i,j)會調用類中的函數調用操作符重載函數,此時A(i,j)可以理解爲:
    A.operator()(i, j)
例1中程序運行結果如下:
    0 1 2 3 4 5 6 7 8 9 10 11
    1 out of bounds!
    2 out of bounds!

在例1中的主函數中異常捕獲語句,我們先運行的是A(5, 3),故而是第一個邊界越界了,因此先拋出“1 out of bounds!”的異常,而後又運行A(2, 6),此時爲第二個邊界越界,拋出“2 out of bounds!”的異常。
 


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