【发布时间】:2015-06-05 11:10:48
【问题描述】:
我正在努力解决我一直想知道的事情。
假设我有一堂课Base
class Base
{
public:
virtual ~Base(){}
virtual bool operator== ( const Base & rhs ) const;
};
现在,另一个类继承自它。它有两个相等运算符:
class A : public Base
{
public:
bool operator== ( const A & rhs ) const;
bool operator== ( const Base & rhs ) const;
private:
int index__;
};
还有一个类也继承自 Base,它也有两个相等运算符:
class B : public Base
{
public:
bool operator== ( const B & rhs ) const;
bool operator== ( const Base & rhs ) const;
private:
int index__;
};
这是我的理解(不一定正确)。 我只能使用第一个运算符来检查相同的类对象是否相等。 然而,我可以使用第二个运算符来检查它们是否是相同类型的类,然后它们是否相等。 现在,又存在一个类,它包裹着 Base 的指针,但它们是多态类型 A 或 B。
class Z
{
public:
bool operator== ( const Z & rhs ) const;
private:
std::shared_ptr<Base> ptr__;
};
首先,我发现我不能让两个 operator== 重载。我没有从编译器中得到任何错误,但是当我尝试运行它时,它只是挂起。我猜它与rtti有关,这超出了我的范围。
我一直在使用并且非常丑陋的东西,正在尝试向下转换,如果可以,请尝试在 Z 类中比较实例:
bool Z::operator== ( const Z & rhs ) const
{
if ( const auto a1 = std::dynamic_pointer_cast<A>( this->ptr__ ) )
if ( const auto a2 = std::dynamic_pointer_cast<A>( rhs.ptr__ ) )
return *a1 == *a2;
else if ( const auto b1 = std::dynamic_pointer_cast<B>( this->ptr__ ) )
if ( const auto b2 = std::dynamic_pointer_cast<B>( rhs.ptr__ ) )
return *b1 == *b2;
return false;
}
这很丑陋,它假设您的 A 类和 B 类有一个相等运算符,该运算符将相同类型的类作为参数。
所以我试图想出一种方法,它可以使用第二种类型的运算符,如果你愿意的话,更不可知论,更优雅。并且失败了。这需要在 A 类和 B 类中都使用它,从而将其从 Z 类移开。
bool A::operator== ( const Base & rhs ) const
{
return ( typeid( *this ) == typeid( rhs ) ) && ( *this == rhs );
}
对于 B 类也是如此。这似乎不起作用(应用程序挂起而没有任何错误)。 此外,它使用某种默认运算符,还是使用基类运算符?理想情况下,它应该同时使用 Base::operator== 和比较类类型。
但是,如果我想要基于 A 类或 B 类的成员进行更详细的比较,例如 index__,那么我显然必须为每个类添加好友,因为当我尝试这个时,它不会编译 (当然,除非我添加一个吸气剂或让它以某种方式可见):
bool A::operator== ( const Base & rhs ) const
{
return ( typeid( *this ) == typeid( rhs ) )
&& (*this == *rhs )
&& (this->index__ == rhs.index__ );
}
有没有优雅、简单的解决方案?我是否仅限于垂头丧气和尝试,还是有其他方法可以实现我想要的?
【问题讨论】:
-
“但是当我尝试运行它时,它只是挂起” - 发布代码。
-
@vsoftco 所以,你的意思是只有 Base 是可比较的,而不是任何派生类?
-
@Alex,一点也不,
operator==是继承的,如果 getter 是virtual,那么你就可以走了。 -
@Alex,我的意思是层次结构应该通过公共
Base接口进行比较,否则设计不是最好的(恕我直言)。当您谈论继承时,要记住的习惯用法是Derived总是也是Base。所以原则上Rectangle不是Square,即使你第一次想把它写成派生类。
标签: c++ inheritance polymorphism equality