【问题标题】:How to implement operator== for polymorphic classes in c++ [duplicate]如何在c ++中为多态类实现operator == [重复]
【发布时间】:2012-10-14 06:25:43
【问题描述】:

可能重复:
What’s the right way to overload operator== for a class hierarchy?

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

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 的替代方法?

【问题讨论】:

  • 我假设您希望operator==() 在传递A 类型的一个对象和B 类型的一个对象时返回false,因为这些类没有直接关系。但是假设您从A 派生一个类AA:当使用一个A 对象和一个AA 对象调用时,您希望operator==() 做什么?
  • 我认为您正在寻找多重调度:stackoverflow.com/questions/1749534/multiple-dispatch-in-c
  • @j_random_hacker 如果两个类具有相同的 typeid 并且所有成员变量具有相同的值,则它们应该比较相等。
  • 那么 PiotrNycz 的答案就是你想要的,同时引入了最少的维护麻烦。
  • @jogojapan 你能告诉我使用多重调度的operator==() 的实现是什么样子的吗

标签: c++


【解决方案1】:

你的方法并不完美。考虑从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);
}

【讨论】:

  • +1。基于 equals() 方法是私有的并且已知在检查相同的动态类型后只能由 operator==() 调用的事实,您可以更改 dynamic_cast&lt;&gt; (这可能需要在类层次结构深度中对数时间)并测试对于 NULL 为直 static_cast&lt;&gt;
  • @j_random_hacker 我们甚至不需要测试 NULL,我们可以使用 dynamic_cast&lt;A&amp;&gt; 代替 dynamic_cast&lt;A*&gt;。不确定static_cast&lt;&gt; 在这里是否安全 - 如果存在多继承和虚拟继承情况怎么办?
  • 如果我们知道动态类型完全相等(并且您使用typeid 的测试已经确定它们是相等的),那么使用static_cast&lt;&gt; 的向下转换保证是安全的。 (这是static_cast&lt;&gt; 最大的用途之一。)
猜你喜欢
  • 1970-01-01
  • 2011-03-01
  • 2013-08-20
  • 2012-02-19
  • 1970-01-01
  • 2012-02-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多