2017-04-17 26 views
0

我定義在C新struct重載操作者()爲一個新的結構

typedef struct TypedObject { 
    ObjectType type; 
    void * value; 
} TypedObject; 

其中對象類型是一個枚舉:

typedef enum ObjectType { 
    type_node, 
    type_int, 
    type_error, 
} ObjectType; 

我想創建一個C++設定的TypedObject指針並從以前的問題我明白,我需要超載operator()爲了比較插入到集合TypedObject指針。

所以我做了如下:

#ifdef __cplusplus 
typedef struct { 
    bool operator() (const TypedObject *lhs, const TypedObject *rhs){ 
     return (lhs->type==rhs->type) && (lhs->value==rhs->value); 
    } 
} ObjComparator; 
#endif 

假設我定義了一組:

std::set<TypedObject *, ObjComparator> mySet; 

你可以假設我用一個迭代器遍歷雖然集。

我想插入TypedObject x到集合中。我用mySet.insert(&x)來插入它的地址..但是一旦我使用mySet.find(&x),它找不到x。撥打電話operator(),但未按預期進行比較。

任何想法是什麼問題可能與我超載的方式operator()?我究竟做錯了什麼? 另外,我是否應該重載不同版本的運營商,如<或==?

回答

1

您提供的Comparator類應執行訂單比較,以便std::set可以使用它來構建二叉搜索樹。

這意味着你的operator()不應該是對稱的 - 默認情況下它是一個「小於」的比較。

一般來說,Comparator類的operator()應該代表你的類嚴格的順序關係,所以它應該是

  • 傳遞 - C(a,b) && C(b,c)意味着C(a,c)
  • 非對稱 - C(a,b)意味着!C(b,a)
  • 總 - !C(a,b) && !C(b,a)意思是「a和b相等」

「平等」的最後定義是std::set在您致電set::find時使用的定義。

解決方案:雖然您肯定會想出一些滿足上述規則的順序,但也許您可以使用一些重構來完成。

如果您的TypedObject具有「地址標識」(即,任何物體只相當於自身),那麼你可以使用默認的比較 - 它完全適用於指針:

std::set<TypedObject *> mySet; 

如果需要成員畢竟比較,通常的做法是這樣的:

bool operator() (const TypedObject *lhs, const TypedObject *rhs) 
{ 
    if(lhs->value < rhs->value) return true; 
    if(rhs->value < lhs->value) return false; 
    return (lhs->type < rhs->type) 
} 

請注意,它只是成員落在operator<。實際上,定義operator<來比較TypedObject s可能會更好,然後從指針Comparator中調用它。

最後,如果你set擁有的對象(即對象在離開設定銷燬),那麼也許這是最好只用

std::set<TypedObject> mySet; 

與重載TypedObjectoperator<。您仍然能夠獲取指向該集合中的對象的指針,並將它們用於您的C API中,並且不需要處理額外的比較器類和內存管理。

+0

那好吧。我應該使用<運算符來比較類型和地址嗎? – baronzo1

+0

@ baronzo1我已經添加了我對可能的解決方案的想法:) – Ap31

+0

謝謝。我會試着看看它是否有效。 – baronzo1

0

您的訂單比較是錯誤的,因爲基於平等它將不能夠創建BST所以正確的代碼應該有如下(注意比較<)

typedef enum ObjectType { 
    type_node, 
    type_int, 
    type_error, 
} ObjectType; 

typedef struct { 
    ObjectType type; 
    void * value; 
} TypedObject; 



typedef struct { 
    bool operator() (const TypedObject *lhs, const TypedObject *rhs){ 
     return (lhs->type==rhs->type) && (lhs->value<rhs->value); 
    } 
} ObjComparator; 

int main() 
{ 
    std::set<TypedObject *, ObjComparator> mySet; 
    TypedObject obj; 
    obj.type=type_int; 
    obj.value=(void*)new int; 
    //*(obj.value)=4; 
    auto insert = mySet.insert(&obj); 
    std::cout<<insert.second<<std::endl; 
    if(mySet.find(&obj) == mySet.end()) 
    { 
     std::cout<<"Not Found..."<<std::endl; 
    } 
    else 
    { 
     std::cout<<"Found..."<<std::endl; 
    } 
    return 0; 
} 
+0

我不能完全理解你在'operator()'函數中所做的更改。爲什麼我應該檢查類型是否相等,但是當涉及到值時,我應該看看一個是否比另一個更小? – baronzo1

+0

好的,你將如何創建BST,你需要比較元素,然後插入到左側,如果它小於插入到右側,如果它大於。所以可以在平等的類型上進行比較,這就是爲什麼類型相同但值小於 – Kapil

+0

爲了記錄,我沒有在這裏處理BST。我正在處理一組'TypedObject'指針。 但我明白你的觀點。謝謝=) – baronzo1