当前位置:  开发笔记 > 编程语言 > 正文

在使用继承时实现operator ==

如何解决《在使用继承时实现operator==》经验,为你挑选了4个好方法。

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

以下是一些示例代码:

#include 
#include 

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*指针,也要确保它们不同.

我该怎么解决这个问题?

谢谢 !



1> JohnMcG..:

你想要做的是基本上"虚拟化"比较运算符.

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

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(&rhs);
         if (pEmployee)
         {
            bRetval = m_Id == pRHSEmployee->m_Id
         }
         return bRetval;
      }
};

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

这也使用RTTI,您可能会或可能不会满意.


如果你要这样做,那么你应该同时调用`this-> doCompare(that)`和`that.doCompare(*this)`来确保对称性

2> Juozas Kontv..:

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



3> Luc Hermitte..:

这个问题没有简洁的解决方案.

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

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

价值对象,Kevlin Henney

Angelika Langer的"平等秘密"(Secrets Of Equals)检查"实体与价值观"部分

EDIT2(2018年11月27日):

这里还有另一个问题,问题在OO设计中也有其根源,而不是在C++中.设计一个reflexive(x == x),symmetric(x == y <=> y == x)和transitive(x == y && y == z => x == z)的比较运算符是不可能的,它也符合Liskov Substitution Principle.在Joshua Bloch的Effective Java,第2版中,有一个彻底的证明.

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



4> Douglas Leed..:

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

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

这是一件坏事(tm).基本上你已经创建了一个非对称的相等运算符

编辑:

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

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有