我有一个实现==运算符的基类.我想编写另一个类,继承基类,并且应该重新实现==运算符.
以下是一些示例代码:
#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*指针,也要确保它们不同.
我该怎么解决这个问题?
谢谢 !
你想要做的是基本上"虚拟化"比较运算符.
由于运营商不能是虚拟的,因此您需要将其委托给其他人.这是一种可能的解决方案.
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,您可能会或可能不会满意.
添加虚函数int Compare(const Person&rPerson)并在运算符中使用它
这个问题没有简洁的解决方案.
在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
一个函数,该函数用于对Point
s的引用,并且需要对它们进行比较.如果{1,2} == {1,2,blue},我们最终会得到{1,2,blue} == {1,2,green}.或者我们拒绝比较有色点的点,这会破坏LSP.等等.没有解决方案.我的结论是继承比较,虽然它很有吸引力,但它不起作用.
如果你有一个人和一个雇员,你仍然会遇到一个重大问题 - 这个人可能与雇员相等,但雇员与雇员不同.即:
(employee == person) != (person == employee)
这是一件坏事(tm).基本上你已经创建了一个非对称的相等运算符
编辑:
好的,没有虚拟运算符 - 添加我认为在其他地方建议的虚拟比较函数 - 但是你仍然存在对称问题.