6

可能重复:
为类层次结构重载 operator== 的正确方法是什么?

我有一个基类和几个派生类,如下面的代码:

class Base
{
public:
    friend bool operator==(const Base&, const Base&);
    virtual ~Base(){}

private:
    virtual bool equals(const Base& other) const = 0;
};

bool operator==(const Base& lhs, const Base& rhs)
{
    return lhs.equals(rhs);
}

class A : public Base
{
public:
    A(int x) : x_(x){}

private:
    virtual bool equals(const Base& other) const;
    int x_;
};

bool A::equals(const Base& other) const
{
    const A* pA = dynamic_cast<const A*>(&other);
    if(!pA) return false;
    return x_ == pA->x_;
}

class B : public Base
{
public:
    B(double y) : y_(y){}

private:
    virtual bool equals(const Base& other) const;
    double y_;
};

bool B::equals(const Base& other) const
{
    const B* pB = dynamic_cast<const B*>(&other);
    if(!pB) return false;
    return y_ == pB->y_;
}

为了能够比较两个派生类,我想要 operator==。问题是如何以面向对象的方式实现这一点(例如,尊重封装、可维护性和可扩展性)。是否有一些推荐的模式来做到这一点?有没有替代上述方法避免dynamic_cast?

4

1 回答 1

3

你的方法并不完美。考虑下一个派生自 的类A

class AA : public A
{
public:
    AA(int x, int y) : A(x), y_(y) {}

private:
    virtual bool equals(const Base& other) const;
    int y_;
};

bool AA::equals(const Base& other) const
{
    const AA* pAA = dynamic_cast<const AA*>(&other);
    if(!pAA) return false;
    return A::equals(other) && y_ == pAA->y_;
}

那么你operatator ==打破了基本规则,它不是对称关系:

   A a(1); 
   AA aa(1,1); 
   assert(a == aa);
   assert(!(aa == a));

简短的解决方法是使用typeid

bool operator==(const Base& lhs, const Base& rhs)
{
    return typeid(lhs) == typeid(rhs) && lhs.equals(rhs);
}
于 2012-10-24T08:31:24.130 回答