2009-10-22 94 views
4

我想在特定的類中按某種順序對某個結構體的向量進行排序。我已經寫了一個類的結構和謂詞函數的定義,並在這個結構和函數的類的方法中運行std :: sort。但編譯錯誤已經發生。 gcc版本是4.0.1,操作系統是Mac OSX。代碼如下:C++ std :: sort類中的謂詞函數

class sample { 
public: 
    struct s { 
    int x; 
    int y; 
    }; 

    bool cmp (struct s a, struct s b) { 
    if (a.x == b.x) 
     return a.y < b.y; 
    else 
     return a.x < b.x; 
    } 

    int func(void) { 
    std::vector <struct s> vec; 

    // ... 

    sort(vec.begin(), vec.end(), cmp); // compilation error 

    // ... 

    return 0; 
    } 
}; 

int main(void) { 
    sample *smp = new sample(); 
    smp->func(); 
    return 0; 
} 

錯誤消息是巨大而複雜的。所以這是它的前兩行。

sortSample.cpp: In member function 'int sample::func()':
sortSample.cpp:51: error: argument of type 'bool (sample::)(sample::s, sample::s)' does not match 'bool (sample::*)(sample::s, sample::s)'
...

代替上述方法,代碼可以通過以下方式正確運行。

  1. 定義struct s和功能cmp()class sample
  2. 刪除 函數cmp()並定義運算符 <的重載struct s

每種方法的示例代碼如下。

1)

struct s { 
    int x; 
    int y; 
}; 

bool cmp (struct s a, struct s b) { 
    if (a.x == b.x) 
    return a.y < b.y; 
    else 
    return a.x < b.x; 
} 

class sample { 
// ... 

2)

struct s { 
    int x; 
    int y; 

    bool operator<(const struct s & a) const { 
    if (x == a.x) 
     return y < a.y; 
    else 
     return x < a.x; 
    } 
}; 

誰能告訴此行爲的機制?爲什麼第一種方法調用編譯錯誤?

謝謝。

回答

12

在第一種情況下,cmp被聲明爲class sample的成員函數,因此需要使用this指針來調用它。由於this指針不可用,編譯器正在抱怨它。通過聲明cmpstatic函數,可以使其工作,因爲靜態函數不需要此指針來調用。在第二種情況下,由於cmp再次被聲明爲獨立函數,它的行爲與靜態函數相同。在第三種情況下(帶有重載運算符),排序算法將負責爲向量中的每個對象調用函數,並因此進行編譯。

6

由於cmp與示例的任何特定實例無關,因此使其成爲靜態成員函數。

5

它可以在你準備使用操作符()被列爲第三種方法:

bool operator() (const s& a, const s& b) const 
{ 
    if (a.x == b.x) 
     return a.y < b.y; 
    else 
     return a.x < b.x; 
} 

sort(vec.begin(), vec.end(), *this); 
+0

哇,這是一個可怕的把戲。謝謝!這是我可以讓比較運算符訪問類實例的成員以及要比較的兩個對象的唯一方法 - 這真的有所幫助,因爲在我的情況下,它允許比較對象使用相對的32位索引到一個64位指針。 – Deadcode 2010-02-13 12:55:28

+0

請注意,調用sort()的方法會將* this的副本傳遞給它,而不是引用或指針,因此如果使用此技巧,請確保副本僅包含謂詞所需的成員 - 最好只有一個32位或64位成員(必要時使用「this」的繼承和投射)。 – Deadcode 2010-02-13 14:29:38

+0

另請注意,* this的副本不僅被傳遞給sort(),而且還會繼續遞歸傳遞給實用函數sort()使用,具體取決於正在使用的STL實現。 – Deadcode 2010-02-13 14:36:47

0

我認爲類之外定義cmp是最好的,因爲你只能做一個功能的成員函數,當您需要它可以訪問課堂中的一些私人功能,從邏輯上來說,它感覺就在那裏。 cmp只是一個實用函數,它爲您的類sample提供了實現的功能,但實際上並不需要訪問私有成員。此外,它可能不會在對象的上下文中被調用(它的唯一操作在其參數上工作; this指針上沒有任何操作),也不必在類sample::cmp的上下文中調用它。雖然看起來像一個微不足道的小問題,但通常不必要的訪問權限可能是許多軟件錯誤或設計卷積來源的開始。

完成上述操作的附加好處是您的std::sort的調用將起作用,這將回答您的問題。