我有一个实现==运算符的基类。 我想编写另一个类,继承基类,并且应该重新实现==运算符。
以下是一些示例代码:
#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 *指针,也要确保它们不同。
我该如何解决这个问题?
谢谢!
答案 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。