所以,我創建了一個可比較的基類(la Java),它在C++中完成重載比較運算符的工作。它是:
template <class T>
class Comparable {
public:
bool operator== (const T& rhs) const { return this->compare(rhs) == 0; }
bool operator!= (const T& rhs) const { return !(*this == rhs); }
bool operator< (const T& rhs) const { return this->compare(rhs) < 0; }
bool operator<= (const T& rhs) const { return (*this == rhs) || (*this < rhs); }
bool operator> (const T& rhs) const { return this->compare(rhs) > 0; }
bool operator>= (const T& rhs) const { return (*this == rhs) || (*this > rhs); }
protected:
virtual int compare (const T& rhs) const = 0;
};
子類對象有一個ID和需要作爲排序鍵的數據。我已經實現了每個ID,使得具有相同ID的對象返回0,並且如果它們不是相同的ID,則根據它們的數據進行排序。這裏有一個例子:
int Foo::compare(const Foo& rhs) const
{
if (_id == rhs._id)
return 0;
// _value is integer data; comparison should sort on this
if (_value == rhs._value)
{
// OK, same data, now sort on ID's
return _id.compare(rhs._id);
}
// Sort on value
return _value - rhs._value;
}
到目前爲止,我認爲這麼好。
但是,當我嘗試將Foo對象存儲在std :: set容器中時,該設置不會消除重複項。也就是說,其中仍然會有對象包含相同的ID,即使這應該被視爲相同。
有沒有人有任何想法是怎麼回事?
編輯:有很多關於爲什麼代碼是這樣設計的問題。
有兩個條件我需要滿足:
- 對象具有相同的ID必須被認爲是「相同的」對象,而不管值。
- 不具有相同ID的對象必須根據它們的值進行排序(該值是什麼,取決於對象的類型)。
這是因爲創建這些對象的數據來自未經驗證的源。如果該源提供的數據具有相同的ID但數據不同,則這是無效的數據。
編輯2:關於std :: map的嚴格弱排序。假設您有兩個Foo對象A和B.
如果它們的ID相同,則A < B爲假,而B < A爲假。 如果他們的ID的不相等,則A < B是真的還是假的,這取決於它們的值,和B < A是甲< B.
相反如果這不能滿足嚴格的排序規則?
在任何情況下,如果std :: set使用小於運算符(因爲它默認情況下),它不應該按照設計工作嗎?編號3:std::set
,而不是std::map
。這真是我的愚蠢。道歉。
您的基類缺少虛擬析構函數。 – chris
if(_id == rhs._id) return 0; 這看起來很奇怪 - 這意味着它表示不管值如何都是平等的,但如果「值」相等,則稍後處理ID比較。哪一個? – Joe
此外,這是如何區分具有相同ID但不同值的數據與具有不同ID排序的數據?在這方面你的函數是不明確的(我認爲,你不會顯示_id.compare),那麼2個具有相同ID的值相差2的項和2個ID相差2的項將被視爲相等。 – Joe