2011-01-31 26 views
2

我發現這個代碼在Wikipedia幫助理解函數對象的工作?

class compare_class { 
    public: 
    bool operator()(int A, int B) const { 
    return A < B; 
    } 
}; 
... 
// Declaration of C++ sorting function. 
template <class ComparisonFunctor> 
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c); 
... 
int main() { 
    int items[] = {4, 3, 1, 2}; 
    compare_class functor; 
    sort_ints(items, sizeof(items)/sizeof(items[0]), functor); 
} 

起初我想知道A和B的參數是怎麼傳遞給操作者()(INT A,INT B),當算符,sort_ints被提及,甚至沒有任何括號。

然後我覺得A和B正在傳遞給sort_ints函數中的函數對象。但是,那麼sort_ints的聲明不應該使用'ComparisonFunctor * * * c'而不是'ComparisonFunctor c',因爲它正在接收函數的地址?

在sort_ints函數裏面,函子調用functor會像這樣做嗎?

functor(*begin_items, *(begin_items+1)); 

回答

6

要理解爲什麼sort_ints取其參數的值,你要記住的是,對象被傳遞因爲比較器不一定是一個函數指針。例如,如果您使用compare_class函數對象進行比較,那麼您傳遞給該函數的是compare_class類型的具體對象。你沒有傳遞compare_class::operator()的地址,因爲operator()是一個成員函數,而不是一個自由函數。即,下面的代碼:

compare_class myComparator; 
myComparator(a, b); 

轉換成

compare_class myComparator; 
myComparator.operator() (a, b); 

因此,參數需要通過值,而不是由指針採取在比較器,因爲它需要一個接收器對象,而不是一個指向成員函數的指針或指向接收者對象的指針。

+0

這是否意味着sort_ints的第三個參數實際上是通過值來獲取整個對象?如果我們正在處理大型對象,那麼這不會太差嗎? – Nav 2011-01-31 05:55:48

2

請注意,compare_class是一類。所以它可以被聲明,並以你使用其他類的方式作爲函數參數傳遞。其次,compare_class實施operator()。這使您可以執行以下操作:

compare_class obj; 
obj(1, 2); 

現在,上述代碼片段中的第二條語句看起來像是一個函數調用!所以從某種意義上說,實現operator()的類的任何對象都可以像函數一樣使用。

這就是函數對象的要點。此外,它與函數指針相比​​還有其他優勢,您可以在您發佈的鏈接中找到相同的鏈接。

編輯

裏面sort_ints(),仿函數是意料中的事像下面這樣:

for (int i = 1; i < num_items; i++) 
    if (c(begin_items[i-1], begin_items[i])) 
    { 
     // begin_items[i-1] is less than begin_items[i], do stuff 
    } 
+0

謝謝,但我不想理解函數指針的一般概念。我想了解在這個特定的例子中值是如何傳遞給它的,因爲sort_ints的內部代碼是不可用的,因爲sort_ints似乎沒有接收到函數指針。我很困惑它是如何工作的。 – Nav 2011-01-31 05:44:37

1

是的,這是正確的。函數調用操作符應用於對象的名稱,而不是對象的方法。此外,你並沒有傳遞函數的地址,你正在傳遞(複製)一個對象。函子對象沒有數據成員,只有一個運算符()。

3

正如您所指出的那樣,沒有什麼在sort_ints的使用情況暗示了比較函子的要求:

compare_class functor; 
sort_ints(items, sizeof(items)/sizeof(items[0]), functor); 

沒有什麼在sort_ints本身之一:

template <class ComparisonFunctor> 
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c); 

而且在class_compare,我們只能通過觀察它的功能推斷出它沒有提供其他功能:

class compare_class 
{ 
    public: 
    bool operator()(int A, int B) const { return A < B; } 
}; 

編譯器確實將它留下,直到它試圖編譯sort_ints的實現時,使用它實例化的類型,然後解決它是否全部掛在一起。 sort_ints必須具有完全相同你提到的一種說法:

c(*begin_items, *(begin_items+1)); // note: functor argument is "c" 

所以,你的理解是對所有罪狀正確的。但是,值得注意的是,提議的C++ 0x功能稱爲Concepts,旨在使sort_int的需求更加明確,而不需要查看它的實現。不幸的是,C++ 0x不得不放棄這個功能,因爲沒有足夠的時間和經驗來確保它是最優的。希望將來的C++版本將包含這樣的特性。你可以在網上找到許多關於Concepts的討論,他們應該幫助你更好地理解整體問題。

這是一個重要的問題,因爲當你只有部分難題時 - 比如你想使用sort_ints函數,但沒有示例ComparisonFunctor,那麼你必須研究sort_ints的實現,以知道如何創建Functor除非你非常幸運,並且有很好的最新文檔)。您可能會意外地使您的代碼太依賴於現有的實現,以便在稍後更改sort_int的實現時,即使它足夠巧妙,不會中斷測試用例或其他用戶的代碼,或者期望。提供的ComparisonFunctor中的一個小錯誤也可能會在sort_int的某個地方產生一個非常複雜且令人困惑的編譯器錯誤消息 - 這不是向用戶提供抽象服務的好方法。讓我們希望概念能夠在一天之內...!