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

How to see if two polymorphic objects are equal?

本文关键字:对象 多态 两个 是否 何判断 判断      更新时间:2023-10-16

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

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
}

我会使用"好奇循环模板"模式,但是在基类和派生类之间有一个辅助类。

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

编写一个helper类,负责将比较重定向到动态类型类。这个助手类有两个模板类型参数:一个基类和一个具体类;这个类应该从基类派生:
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;
    }
};

注意:帮助类模板只需要一次,不仅对每个基类一次,而且在整个代码库中一次,即使你有多个基类,你想基于多态类型进行比较。

现场演示

  1. operator==函数在A中创建虚成员函数。使用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;
       }
    }
};