在C#中,可以針對任何對象測試任何對象的相等性,因爲一切都從Object繼承。C++相等測試'對象'
在C++中,情況並非如此。我想重載傳遞給任何未知類的==運算符,並在運行時檢查不等式,而不是編譯時間。 (我收到錯誤binary '!=' : no operator found which takes a left-hand operand of type
)。
現在我想爲TDD的目的。
我該怎麼做?
在C#中,可以針對任何對象測試任何對象的相等性,因爲一切都從Object繼承。C++相等測試'對象'
在C++中,情況並非如此。我想重載傳遞給任何未知類的==運算符,並在運行時檢查不等式,而不是編譯時間。 (我收到錯誤binary '!=' : no operator found which takes a left-hand operand of type
)。
現在我想爲TDD的目的。
我該怎麼做?
在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#實現按成員平等這無疑更有意義,但也通常不會有什麼想要的,非常低效的啓動(因爲它使用反射)。
這可能是不重要的,但是你爲什麼'reinterpret_cast'到'字符*'?這試圖拋棄引用的'const'。我也不清楚爲什麼你不用比較void const *(通過靜態/「隱式」轉換)。 – dyp
@DyP關於'const'的好處。使用char *的原因是'char *'是'byte *'的一個(名字很少)的同義詞,即邏輯上接近一個內存地址的東西。我不知道'void *'是什麼(除了擦除類型)。我不使用它。 –
這是什麼原因不推薦? – happygilmore
模仿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。
默認情況下,運營商==由 確定兩個引用是否表示相同的對象,所以引用 類型並不需要執行才能獲得這一 功能的==操作符引用相等測試。當類型是不可變的,這意味着包含在 的實例中的數據不能被改變,重載運算符==比較 值相等,而不是參考平等可以是有用的,因爲如 不可變的對象,它們可以,只要認爲是相同的他們 具有相同的值。在非不可變類型中覆蓋運算符==不推薦使用 。
發佈您的代碼:) – Drax
你說的平等是什麼意思?有一些方法可以定義什麼是相等的意思,哪些恕我直言是你無法比較'C++'中的任意對象的原因之一。一些選項:同一個對象(即地址),按位相同,平等概念,... –
TDD在強類型語言一般都需要你來決定你處理,你寫測試什麼類型的。 –