2014-01-07 3 views
0

C#에서는 모든 것이 Object에서 상속되므로 모든 객체에 대해 동등성을 테스트 할 수 있습니다.C++ 동등 테스트 'Object'

C++에서는 그렇지 않습니다. 알 수없는 클래스를 전달하는 == 연산자를 오버로드하고 런타임에 컴파일 타임이 아닌 비항 등을 확인하고 싶습니다. (나는 오류 binary '!=' : no operator found which takes a left-hand operand of type를 얻는다).

지금 당장 TDD 용으로 이것을 원합니다.

어떻게하면됩니까?

+0

코드 게시 : – Drax

+6

평등이란 무엇을 의미합니까? 평등이란 무엇을 의미하는지 정의하는 몇 가지 방법이 있습니다. IMHO는 '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); 
} 

...이 (참조 정체성 1을 구현하는) 당신의 대체 케이스가 될 것입니다. 종류는 (SFINAE를 통해) 해당 조작을 구현하는 경우 지금 당신은 하나를 추가 할 수 있습니다

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

이 반복하는,이 권고되지도 일반적으로 도움이되지도. 그것은 거의 무의미합니다. 여러분은 이미 여러분의 객체를 비교할 수 있다는 것을 이미 알고 있습니다. 또는 비교가 시작하는 것이 타당하지 않습니다.

C#의 디자인이 상당히 나쁜 것입니다. 단순히 일반적인 "평등"개념이 없으며 C#의 Object 유형이이 점에 대해 지나치게 지정됩니다. struct들에 대한


1 은 C#을 (가 반사를 사용하고 있기 때문에) 부팅 매우 비효율적 틀림없이 더 의미가 있지만, 마찬가지로 일반적으로 원했던하지 무엇을하고 memberwise 평등을 구현합니다.

+0

중요하지는 않지만 왜'reinterpret_cast'를'char *'에'reinterpret_cast'합니까? 그것은 참조의'const'를 버리려고합니다. 왜 당신이'void const *'를 대신 (static/"implicit"cast를 통해) 비교하지 않는지도 분명하지 않습니다. – dyp

+1

@DyP'const'-ness에 대한 좋은 지적. 'char *'을 사용하는 이유는'char *'가'byte *'와 동의어 (약칭)이기 때문에 논리적으로 메모리 주소에 접근하는 것이다. 나는'void * '가 (지워진 타입을 제외하고) 어떤 것이 있는지 전혀 모른다. 나는 그것을 사용하지 않는다. –

+0

이것이 권장되지 않는 이유는 무엇입니까? – happygilmore

2

(C#을 더 CONST가 없습니다 외에)는 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를 대체해야합니다. 형식이 IComparable을 구현하면 이 같음을 재정의해야합니다.기본적으로

, 연산자 == 두 개의 참조가 같은 객체를 나타냅니다 그래서 만약이 기능을 얻기 위해 운영자 ==를 구현하지 않아도 유형을 참조하는 결정 에 의해 참조가 동일한 지 어떤지를 판정합니다. 형식이 변경되지 않으면 에 포함 된 데이터를 의미 할 수 없으므로 연산자를 == 오버로드하여 참조 평등 대신 값의 같음을 비교하면 유용 할 수 있습니다. 불변 개체로 간주 될 수 있기 때문에 그들은 같은 값을 가지고 있습니다. 비 변경 가능 유형에서 연산자 ==를 대체하면 이 권장되지 않습니다.