【发布时间】:2015-09-24 17:18:58
【问题描述】:
这是一个非常简单的类层次结构:
class A
{
public:
A( int _a ) : a( _a ) {}
virtual bool operator==( const A& right ) const
{
return a == right.a;
}
virtual bool operator!=( const A& right ) const
{
return !( *this == right );
}
int a;
};
class B : public A
{
public:
B( int _a, int _b ) : A( _a ), b( _b ) {}
virtual bool operator==( const B& right ) const
{
return A::operator==( right ) && b == right.b;
}
int b;
};
如您所见,运算符 != 是在基类中定义的。因为我很懒,不想在所有的派生类里都复制这么简单的代码。
不幸的是,使用此代码:
A a4(4), a5(5), a4bis(4);
assert( a4 == a4bis );
assert( a4 != a5 );
B b1(4,5), b2(4,6);
assert( !(b1 == b2) );
assert( b1 != b2 ); // fails because B::operator== is not called!
b1 != b2返回false,因为它执行A::operator!=,然后调用A::operator==而不是B::operator==(即使操作符是虚拟的,因为派生类版本参数不同,它们在vtable中没有链接) .
那么,对于类层次结构,以通用方式处理 != 运算符的最佳方式是什么?
一种解决方案是在每个班级重复它,B 将有:
virtual bool operator!=( const B& right ) const
{
return !( *this == right );
}
但是当你有很多课程时,这很痛苦......我有 30 个......
另一种解决方案是使用通用模板方法:
template <class T>
bool operator!=( const T& left, const T& right )
{
return !( left == right );
}
但这绕过了任何类定义的任何!= 运算符....因此,如果以不同方式声明它可能会有风险(或者如果一个声明== 本身调用!=,它最终会得到一个无限循环...)。所以我觉得这个解决方案非常不安全......除非我们可以限制模板用于从我们层次结构的顶级类派生的所有类(在我的示例中为A)......但我不'认为这根本不可行。
注意:我还没有使用 C++11……很抱歉。
【问题讨论】:
-
此外,目前,
A(42) == B(42, 0)仅比较A部分... -
为了清楚起见并确保 A 继续独立工作(如果您不想要它,则不需要从中派生 B),实现 != for A, B, C , D 以及你在你的层次结构中拥有的任何东西。同样,如果您不需要它们,为什么还需要派生?
标签: c++ operator-overloading comparison-operators