C ++相等测试'对象'

时间:2014-01-07 12:15:48

标签: c++ operator-overloading

在C#中,可以针对任何对象测试任何对象的相等性,因为所有对象都继承自Object。

在C ++中,情况并非如此。我想重载传入任何未知类的==运算符,并在运行时检查不等式,而不是编译时间。 (我收到错误binary '!=' : no operator found which takes a left-hand operand of type)。

现在我想要这个用于TDD目的。

我该怎么做?

2 个答案:

答案 0 :(得分: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类型在这方面被过度指定。


1 对于struct,C#实现成员相等,这可能更有意义,但同样通常不是想要的,并且引导效率非常低(因为它使用反射)。

答案 1 :(得分:2)

模仿C#机制给出(除了C#没有const):

#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是一种虚方法,可以让任何类覆盖它   实现。任何代表值的类,基本上是任何类   值类型或作为组的一组值,例如复数   class,应该重写Equals。如果类型实现IComparable,它   应该重写等于。

     

默认情况下,运算符==测试引用相等性   确定两个引用是否表示相同的对象,因此引用   类型不需要实现operator ==以获得此功能   功能。当一个类型是不可变的时,意味着包含在中的数据   实例无法更改,重载operator ==进行比较   值相等而不是引用相等可能是有用的,因为,as   不可变对象,只要它们可以被认为是相同的   具有相同的价值。在非不可变类型中覆盖operator ==   不推荐。