我有一个基类和几个派生类,如下面的代码:
class Base
{
public:
friend bool operator==(const Base&, const Base&);
virtual ~Base(){}
private:
virtual bool equals(const Base& other) const = 0;
};
bool operator==(const Base& lhs, const Base& rhs)
{
return lhs.equals(rhs);
}
class A : public Base
{
public:
A(int x) : x_(x){}
private:
virtual bool equals(const Base& other) const;
int x_;
};
bool A::equals(const Base& other) const
{
const A* pA = dynamic_cast<const A*>(&other);
if(!pA) return false;
return x_ == pA->x_;
}
class B : public Base
{
public:
B(double y) : y_(y){}
private:
virtual bool equals(const Base& other) const;
double y_;
};
bool B::equals(const Base& other) const
{
const B* pB = dynamic_cast<const B*>(&other);
if(!pB) return false;
return y_ == pB->y_;
}
Run Code Online (Sandbox Code Playgroud)
为了能够比较两个派生类,我想要运算符==.问题是如何以面向对象的方式实现这一点(例如,尊重封装,可维护性和可扩展性).是否有一些推荐的模式可以做到这一点?有没有替代上述方法来避免dynamic_cast?
你的方法并不完美。考虑下一个类源自A:
class AA : public A
{
public:
AA(int x, int y) : A(x), y_(y) {}
private:
virtual bool equals(const Base& other) const;
int y_;
};
bool AA::equals(const Base& other) const
{
const AA* pAA = dynamic_cast<const AA*>(&other);
if(!pAA) return false;
return A::equals(other) && y_ == pAA->y_;
}
Run Code Online (Sandbox Code Playgroud)
那么你operatator ==就违反了基本规则,它不是对称关系:
A a(1);
AA aa(1,1);
assert(a == aa);
assert(!(aa == a));
Run Code Online (Sandbox Code Playgroud)
简短的解决方法是使用typeid:
bool operator==(const Base& lhs, const Base& rhs)
{
return typeid(lhs) == typeid(rhs) && lhs.equals(rhs);
}
Run Code Online (Sandbox Code Playgroud)