2014-01-07 121 views
0

在C#中,可以針對任何對象測試任何對象的相等性,因爲一切都從Object繼承。C++相等測試'對象'

在C++中,情況並非如此。我想重載傳遞給任何未知類的==運算符,並在運行時檢查不等式,而不是編譯時間。 (我收到錯誤binary '!=' : no operator found which takes a left-hand operand of type)。

現在我想爲TDD的目的。

我該怎麼做?

+0

發佈您的代碼:) – Drax

+6

你說的平等是什麼意思?有一些方法可以定義什麼是相等的意思,哪些恕我直言是你無法比較'C++'中的任意對象的原因之一。一些選項:同一個對象(即地址),按位相同,平等概念,... –

+2

TDD在強類型語言一般都需要你來決定你處理,你寫測試什麼類型的。 –

回答

4

在C#中,可以針對任何對象測試任何對象的相等性,因爲所有對象都從Object繼承。

這只是顯然不正確。儘管每個類都繼承了一個Equals方法,但這種方法並不一定有意義,除非它被覆蓋。

可以實現在C++相同,但它是相當不好的做法,可能不是你想要的:

template <typename A, typename B> 
bool equals(A const& a, B const& b) { 
    return reinterpret_cast<char const*>(&a) == reinterpret_cast<char const*>(&b); 
} 

...這將是您的回退的情況下(實施基準身份)。現在,你可以添加一個在類型實現適當的操作(通過SFINAE):

template <typename T> 
auto equals(T const& a, T const& b) -> decltype(a == b) { 
    return a == b; 
} 

但重申一下,這是既不建議也普遍有所幫助。這大多是荒謬的 - 要麼你已經知道(和如何)你可以比較你的對象,或者比較沒有意義。

C#的設計是非常糟糕的。根本沒有普遍的「平等」概念,並且C#的Object類型在這方面是過分指定的。


struct S,C#實現按成員平等這無疑更有意義,但也通常不會有什麼想要的,非常低效的啓動(因爲它使用反射)。

+0

這可能是不重要的,但是你爲什麼'reinterpret_cast'到'字符*'?這試圖拋棄引用的'const'。我也不清楚爲什麼你不用比較void const *(通過靜態/「隱式」轉換)。 – dyp

+1

@DyP關於'const'的好處。使用char *的原因是'char *'是'byte *'的一個(名字很少)的同義詞,即邏輯上接近一個內存地址的東西。我不知道'void *'是什麼(除了擦除類型)。我不使用它。 –

+0

這是什麼原因不推薦? – happygilmore

2

模仿C#機制產生(除C#沒有常):

#include <iostream> 

class Object 
{ 
    public: 
    virtual ~Object() {} 
    virtual bool Equals(const Object& other) const { 
     // C# ReferenceEquals 
     return this == &other; 
    } 
}; 

bool operator == (const Object& a, const Object& b) { 
    std::cout << " Object == Object "; 
    // C# ReferenceEquals 
    return &a == &b; 
} 

class Derived : public Object 
{ 
    public: 
    virtual bool Equals(const Object& other) const { 
     // C# does a test if the object is null - not needed in C++ 
     const Derived* derived = dynamic_cast<const Derived*>(&other); 
     if(derived) return Equals(*derived); 
     else return false; 
    } 

    bool Equals(const Derived& other) const { 
     // Compare the members. 
     return true; 
    } 
}; 

// C# Guideline: Overriding operator == in non-immutable types is not recommended 
bool operator == (const Derived& a, const Derived& b) { 
    std::cout << "Derived == Derived "; 
    // C#: Test references conditions - not needed in C++: 
    //  if (System.Object.ReferenceEquals(a, b)) return true; 
    //  if (((object)a == null) || ((object)b == null)) return false; 
    return a.Equals(b); 
} 


// Test 

template <typename A, typename B> 
void compare(const char* what, const A& a, const B& b) { 
    std::cout << what << ": "; 
    std::cout << ((a == b) ? "True " : "False "); 
    std::cout << " Equals: " << ((a.Equals(b)) ? "True " : "False ") << '\n'; 
} 

int main() { 
    Derived a; 
    Derived b; 
    Object& c = a; 
    Object& d = b; 
    compare("a == b", a, b); 
    compare("a == c", a, c); 
    compare("e == d", c, d); 
} 

輸出:

a == b: Derived == Derived True Equals: True 
a == c: Object == Object True Equals: True 
e == d: Object == Object False Equals: True 

我不建議在C++。

說明(從http://msdn.microsoft.com/en-us/library/ms173147%28v=vs.80%29.aspx

的Equals是一個虛擬方法,從而使任何類重寫其 實現。代表一個值的任何類,基本上任何值類型或一組值(如複數 類)都應該覆蓋Equals。如果類型實現了IComparable,則它應該覆蓋Equals。

默認情況下,運營商==由 確定兩個引用是否表示相同的對象,所以引用 類型並不需要執行才能獲得這一 功能的==操作符引用相等測試。當類型是不可變的,這意味着包含在 的實例中的數據不能被改變,重載運算符==比較 值相等,而不是參考平等可以是有用的,因爲如 不可變的對象,它們可以,只要認爲是相同的他們 具有相同的值。在非不可變類型中覆蓋運算符==不推薦使用 。