【问题标题】:How to see if two polymorphic objects are equal? [duplicate]如何查看两个多态对象是否相等? [复制]
【发布时间】:2014-06-16 17:46:09
【问题描述】:

如何判断两个多态对象是否相等?例如

struct A {};

struct A1 : public A
{
    int i;
    bool operator==(A1 const& other) const { return i == other.i; }
};

struct A2 : public A
{
    float f;
    bool operator==(A2 const& other) const { return f == other.f; }
};

bool isEqual(A const& x, A const& y)
{
    if (typeid(x) != typeid(y))
        return false;

    ... // Then how to compare when they have same type. Any way to cast them 
        // to their dynamic types by typeid or others
}

【问题讨论】:

  • 查看访问者模式。你需要实现类似的东西或者使用dynamic_cast和virtual bool equals(base const & other) const。
  • 您是否尝试过编译问题中已经存在的代码?
  • 你为什么要这样做?由于 A1+A2 没有 ==,所以它不会编译,所以你可以安全地比较 x 和 y,不是吗?这个问题对我来说不是很清楚。
  • @quantdev 如果使用多态,它们的静态类型将是 A 和 A。 IE。你有一些vector<A*> 来存储 A1 和 A2,现在的问题是:如何将两个这样的对象(不是它们的指针)与覆盖的比较进行比较?
  • 我不确定您在寻找什么。如果它们具有相同的类型,您是否要检查二进制相等对象(即所有内容位到位相等)?或者您想使用成员数据的子集进行比较(如果有一些与比较无关的 tmp 数据)?还是您在寻找多态相等?

标签: c++ polymorphism


【解决方案1】:

我会使用“Curiously Recurring Template”模式,但在基类和派生类之间有一个帮助类。

首先,在您的基类A 中添加一个纯虚拟operator==。

编写一个帮助类,负责将比较重定向到动态类型类。这个帮助类有两个模板类型参数:一个基类和一个具体类;这个类应该派生自基类:

template<typename Base, typename Derived>
struct PolymorphicComparable : public Base {
    ...
};

在这个类中,你实现operator==(如果稍后Base==A,这将是一个覆盖):

bool operator==(const Base &other) const {
    // first check if the dynamic types match
    if (typeid(other) != typeid(Derived))
        return false;

    // cast to the concrete types; thanks to the check above this is safe
    const Derived & a = static_cast<const Derived&>(*this);
    const Derived & b = static_cast<const Derived&>(other);

    // redirect to Derived::operator==(Derived)
    return a == b;
}

现在,A 的子类不直接继承 A 而是上面的类(这是“奇怪的循环模板”),并且每个都实现自己的 operator==,不需要额外的代码:

struct A1 : public PolymorphicComparable<A,A1>
//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
    int i;

    bool operator==(const A1 &other) const {
        return i == other.i;
    }
};

注意:帮助类模板只需要一次,不仅每个基类需要一次,而且在整个代码库中也需要一次,即使您有多个要根据多态类型。

Live Demo

【讨论】:

    【解决方案2】:
    1. 在A 中为operator== 函数创建一个虚拟成员函数。使用operator== 实现operator!=。

      struct A
      {
          virtual bool operator==(A const& other) const = 0;
          bool operator!=(A const& other) const
          {
              return !(*this == other);
          }
      };
      
    2. 在具体类中实现operator== 函数并添加必要的检查。

      struct A1 : public A
      {
          int i;
          virtual bool operator==(A const& other) const
          {
             // Do dynamic cast to make sure that other is of type A1.
             A1 const* otherPtr = dynamic_cast<A1 const*>(&other);
             if ( otherPtr == NULL )
             {
                 return false;
             }
             else
             {
                return i == otherPtr->i;
             }
          }
      };
      

    更新

    如果A 有比较两个对象时需要考虑的数据...

    struct A
    {
        virtual bool operator==(A const& other) const
        {
           return (j == other.j);
        }
    
        bool operator!=(A const& other) const
        {
            return !(*this == other);
        }
        int j;
    };
    
    struct A1 : public A
    {
        int i;
        virtual bool operator==(A const& other) const
        {
           if ( !(A::operator==(other)) )
           {
              return false;
           }
    
           // Do dynamic cast to make sure that other is of type A1.
           A1 const* otherPtr = dynamic_cast<A1 const*>(&other);
           if ( otherPtr == NULL )
           {
               return false;
           }
           else
           {
              return i == otherPtr->i;
           }
        }
    };
    

    【讨论】:

    • 这很简单。它假设基本层次结构中没有要比较的数据。
    • @Nawaz:这个答案确实没有表明这一点,但是当有多个要比较的子对象时,该方法仍然有效。基础子对象通过调用基础A::operator==(other) 进行比较。
    • @Nawaz,请查看我的更新。这正是 Ben Voigt 所建议的。
    猜你喜欢
    • 2017-02-20
    • 2016-10-22
    • 2016-06-27
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多