2011-11-14 74 views
1

我正在模擬一個隊列類,所以我可以將它用於int和任何我需要定義的結構。如何將函數回調傳遞給類成員?

我需要將一個比較函數傳遞給類構造函數,一個預定義的比較函數,用於整數等,然後將其留給客戶端以提供它們可能需要的任何比較函數。但我該怎麼做?

template<typename Type> 
int cmpFn(Type one, Type two) 
{ 
    if (one < two) return -1; 
    if (one > two) return 1; 
    return 0; 
} 

template <typename Type> 
class Queue 
{ 
    public: 
     Queue() 
     { 
      Type *list = new Type[size]; 
      // What do I do now? 
      // How to define this constructor? 
      // It must pass a comparison function 
      // to a private sort method in this class. 
     } 
    private: 
     void sortFunc(Type list, int(fn)(Type one, Type two)=cmpFn); 
}; 

有可能在上述代碼中的一些錯誤,因爲我只是把它寫下來,從我的頭頂,使我的問題更加清晰。但是我感興趣的是如何在定義類時將比較函數傳遞給排序方法。

這是個人練習,我沒有參加任何課程,也沒有任何導師。我已經使用了一段時間了,但我不能提出正確的答案......我想我並沒有向谷歌先生提出正確的問題。

P.S. 客戶可能要爲任何類型的數據提供比較的功能,如:

struct individual 
{ 
    string name; 
    int age; 
    double height; 
}; 

我猜測,構造函數是這樣的:

Queue(int (*fn)(Type, Type) = cmpFn); 

但是我怎麼定義/實現這個?它不是一個使用這個回調函數的Queue對象本身,而是它的方法:sort();

+0

這不是一個答案,但在C++的精神,我會設計這個不同的;即期望'T'帶有'operator <'或'std :: less '的專門化,並將其用於排序。甚至可能公開迭代器,儘管這可能對隊列式結構沒有幫助。 –

回答

2

這裏的工作中,我想你想要編譯的例子:

#include <cstddef> 
#include <string> 
#include <iostream> 

template<typename Type> 
int cmpFn(Type one, Type two) 
{ 
    if (one < two) return -1; 
    if (one > two) return 1; 
    return 0; 
} 

template <typename Type> 
class Queue 
{ 
    public: 
     // This is the typedef for your callback type 
     typedef int (*callback)(Type one, Type two); 

     Queue(Type *list, size_t size, callback func = cmpFn) 
     { 
      sortFunc(list, size, func); // works too 
     } 

    private: 
     void sortFunc(Type *list, size_t size, callback func) { 
      for (size_t i=0; i<size; i++) { 
       for (size_t j=0; j<size; j++) { 
        if (i == j) continue; 

        int val = (*func)(list[i], list[j]); 
        switch (val) { 
         case 1: 
          std::cout << list[i] << " is greater than " << list[j] << "\n"; 
          break; 
         case -1: 
          std::cout << list[j] << " is greater than " << list[i] << "\n"; 
          break; 
         case 0: 
          std::cout << list[i] << " and " << list[j] << " are equal\n"; 
          break; 
        } 
       } 
      } 
     } 

}; 

int stringCmp(std::string one, std::string two) { 
    if (one.size() < two.size()) return -1; 
    if (one.size() > two.size()) return 1; 
    return 0; 
} 

int main() { 
    // compare ints, use generic comparison function (cmpFn) 
    int myInts[2] = {1, 2}; 
    Queue<int> qi(myInts, 2); 

    // compare strings, use our own comparison function (stringCmp) 
    std::string myStrings[2] = {"foo", "bar"}; 
    Queue<std::string> qs(myStrings, 2, stringCmp); 

    return 0; 
} 

編譯和執行上面的程序應該給你這樣的輸出:

2 is greater than 1 
2 is greater than 1 
foo and bar are equal 
bar and foo are equal 

基本上它:

  • Queue構造函數接受list數組,它的大小和一個調用後退功能。
  • 如果未提供回調函數,則使用通用函數(cmpFn)。
  • 然後它調用sortFunc,它循環訪問list數組中的所有元素,並使用回調函數進行比較。

在上面的代碼中,您可以使用intstd::string的示例。

+0

謝謝!這幾乎是我需要的。現在我只需要想出如何在類對象中存儲回調函數引用。相反,我不希望sortFunc被構造函數自動調用,而是客戶端將在需要時以調用myqueue.sortFunc()方式調用它。或myqueue-> sortFunc();客戶端在構造對象時確定了用於排序的比較函數:隊列 myqueue(cmpFuncStrings); – user971191

+1

@ user971191:爲此你必須公開'sortFunc'(它是私人的,所以我認爲你不會)。如果你想存儲回調函數,'callback'被定義爲一個類型,所以只需聲明該類型的成員並在構造函數中定義它。 – netcoder

+0

我一直都在我的眼睛後面......我感謝你指出了它! :) – user971191

0

也許是這樣的:

void sortFunc(Type list, int(*fn)(Type one, Type two) = cmpFn<Type>); 

可能最好通過常量引用,而不是通過複製傳遞參數。誰知道他們是否可以複製?

+0

感謝您的回覆,但我該如何讓這個類存儲客戶端提供的比較功能?客戶端將提供如何比較列表中包含的元素。我只自己定義標準比較函數。我真的迷失了。 – user971191

+1

啊,我明白了。您可以使比較函數成爲您的類的模板參數,然後添加相應的構造函數參數。看看如何實現'set'(或者至少檢查它的公共接口)。 –

+0

@ user971191:如果你不希望它成爲模板參數的一部分,你將不得不做一些類型的擦除。 –

相關問題