在使用继承时实现operator ==

时间:2009-02-19 15:15:06

标签: c++

我有一个实现==运算符的基类。 我想编写另一个类,继承基类,并且应该重新实现==运算符。

以下是一些示例代码:

#include <iostream>
#include <string>

class Person
{
public:
  Person(std::string Name) { m_Name = Name; };

  bool operator==(const Person& rPerson)
  {
    return m_Name == rPerson.m_Name;
  }

private:
  std::string m_Name;
};

class Employee : public Person
{
public:
  Employee(std::string Name, int Id) : Person(Name) { m_Id = Id; };

  bool operator==(const Employee& rEmployee)
  {

    return (Person::operator==(rEmployee)) && (m_Id == rEmployee.m_Id);
  }

private:
  int m_Id;
};

void main()
{
  Employee* pEmployee1 = new Employee("Foo" , 1);
  Employee* pEmployee2 = new Employee("Foo" , 2);

  if (*pEmployee1 == *pEmployee2)
  {
    std::cout << "same employee\n";
  }
  else
  {
    std::cout << "different employee\n";
  }

  Person* pPerson1 = pEmployee1;
  Person* pPerson2 = pEmployee2;

  if (*pPerson1 == *pPerson2)
  {
    std::cout << "same person\n";
  }
  else
  {
    std::cout << "different person\n";
  }
}

此示例代码给出以下结果:

different employee
same person

我希望在哪里,即使处理Person *指针,也要确保它们不同。

我该如何解决这个问题?

谢谢!

9 个答案:

答案 0 :(得分:9)

您要做的是基本上“虚拟化”比较运算符。

由于运营商不能是虚拟的,因此您需要将其委托给其他人。这是一种可能的解决方案。

class Person
{
   public:
      /* ... */
      bool operator==(const Person& rhs)
      {
         return m_Name == rPerson.m_Name && this->doCompare(rhs);
      }
   private:
      virtual bool doCompare() = 0;
   };
}
class Employee : public Person
{
   /* ... */
   private:
      virtual bool doCompare(const Person& rhs)
      {
         bool bRetval = false;
         const Employee* pRHSEmployee = dynamic_cast<const Employee*>(&rhs);
         if (pEmployee)
         {
            bRetval = m_Id == pRHSEmployee->m_Id
         }
         return bRetval;
      }
};

这个问题没有说清楚人是否需要成为一个具体的阶级。如果是这样,你可以使它不是纯虚拟的,并实现它以返回true。

这也使用了您可能会或可能不会满意的RTTI。

答案 1 :(得分:7)

添加虚函数int Compare(const Person&amp; rPerson)并在运算符中使用

答案 2 :(得分:6)

这个问题没有解决方案。

在C ++中,实际上这不是问题。在平等的基础上比较实体有什么意义?

编辑:关于适用于实体的平等相关性的一些冥想链接:

EDIT2(2018年11月27日):

这里还有另一个问题,问题在OO设计中也有其根源,而不是在C ++中。设计一个自反(x == x),对称(x == y <=> y == x)和传递(x == y && y == z => x == z)的比较运算符是不可能的,它也符合Liskov Substitution Principle。约书亚布洛赫的 Effective Java ,第二版中充分证明了这一局限。

TL; DR:假设我们ColouredPoint继承自Point,这个函数适用于对Point的引用,需要对它们进行比较。如果 {1,2} == {1,2,blue} ,我们最终会得到 {1,2,blue} == {1,2,green} 。或者我们拒绝比较有色点的点,这会破坏LSP。等等。没有解决方案。我的结论是继承比较,虽然它很有吸引力,却不起作用。

答案 3 :(得分:6)

如果您有一个人和一个雇员,您仍然会遇到重大问题 - 该人可能与员工相等,但员工与员工不同。即:

(employee == person) != (person == employee)

这是一件坏事(tm)。基本上你已经创建了一个不是symmetric

的等于运算符

编辑:

好的,没有虚拟运算符 - 添加我认为在其他地方建议的虚拟比较函数 - 但是你仍然存在对称问题。

答案 4 :(得分:2)

这里最大的问题是 - 你如何确定平等?

可以将任何对象与层次结构中的任何其他对象进行比较吗?是否只能比较相同类型的对象?比较的标准在哪里?

解决方案的实施将取决于这些问题的答案。

答案 5 :(得分:1)

让同一个人与两个不同的员工相等是没有意义的,但这是你的班级设计所允许的。你最好安排身份与一个人联系。然后你问a.identity()== b.identity()。

答案 6 :(得分:1)

为了使operator==对称,您必须让具有相同共享详细信息的人和员工不同,以便:

Person p("Foo");
Employee e("Foo" , 1);
p == e; // false
e == p; // false

这是不直观但必要的。

为此,您可以使用typeid keyword

bool operator==(const Person& other) const
{
     return m_Name == other.m_Name && typeid(other) == typeid(*this);
}

当然Person必须是多态类型(至少有一个虚函数)。

答案 7 :(得分:0)

您也可以在类范围之外使用operator ==。在这种情况下,您可以创建必要的重载或通过模板使其通用。

答案 8 :(得分:-1)

你需要使Person :: operator == virtual。