所以,在阅读一些所谓的问题和答案之后,我仍然不明白为什么使用
friend bool operator==( BaseClass const &left, BaseClass const &right )
代替
bool operator==( BaseClass const &right )
现在我有这样的事情http://pastebin.com/pKsTabC0 (固定) -和它似乎很好地工作。 但是,也许我失去了一些东西? 有什么建议?
更新1
好吧,我改变了源,使其工作权http://ideone.com/fIAmB 。 去除不需要的虚拟和添加常量。 不过我不明白为什么要使用的朋友...
你得到的功能不具有相同的签名父运营商,所以它隐藏父比较,而不是覆盖它。 这意味着你不能使用虚拟岬无论如何,因为静态类型左侧参数的确定调用的函数。
这就是为什么虚拟比较常规方法是一种非成员平等操作者分派给在基类的虚拟比较函数。
不要考虑你,虽然,因为它可能是一个设计的气味是有,你可以使用,而不是替代的设计比较虚的特定需求。
还要注意的是成员的比较(平等在这种情况下)运营商平时应该是const
。
编辑:看来你可能只关心基于静态类型左手的说法,这应该是一个简单的问题的比较。 在这种情况下,你的代码处理,除非左手参数是隐式类型转换到所有的情况下Base
或Derived
的不是继承(转换运算符或转换构造)其他一些机制。 如果你不关心的情况下,则该成员平等的罚款。
作为最后一个音符,如果比较可以完全通过公共接口来完成,我们(几乎)总是喜欢非成员,非友元函数,无论它是否是一个运营商。
EDIT2(非成员,非友的真快概述):
例如,假设您的类有一个公共key
方法,如果两个实例的密钥是相同的,你要拨打的对象相等。 然后,在不使用的朋友或成员平等的经营者,你可以写你的平等独立的:
bool operator==(const MyType& left, const MyType& right)
{
return left.key() == right.key();
}
没有错本身有一个成员函数,但自由的功能是比较通用的。 成员函数被迫有左侧的操作数是类型BaseClass
或儿童型,而free函数接受隐式转换为任何类型BaseClass
,而不是仅继承树的一部分类型。
我看到的最大的问题virtual bool operator==( BaseClass const &right )
是,如果没有多个动态调度*,下面的断言将失败。
class Derived1 : public BaseClass {
bool operator==( BaseClass const &right ) override {
return true;
}
}
class Derived2 : public BaseClass {
bool operator==( BaseClass const &right ) override {
return false;
}
}
Derived1 d1;
Derived2 d2;
assert((d1 == d2) == (d2 == d1));
友元函数,可向处理这个问题,但说实话,这是一个很大的麻烦,得到这样的权利,没有多分派。 即使有多个调度,对这样一个多态平等操作正确的语义可能不容易拿出。
*多种动态调度是不是只是做一个以上的参数的动态调度能力, this
。
有你试图让两个独立的点。 首先,操作者实现作为成员函数,而不是一个独立的功能。 其次,实现它作为一个虚拟函数(你甚至把在标题)。
什么是你想通过“虚”的部分说的是不明确的。 在您的代码示例派生类运营商没有覆盖基类的运营商,因为他们的签名不匹配。 有在你的例子没有多态性。 所以,我不明白你的住它“工作正常”的意思。 它并没有真正在所有(如“虚拟”的运营商)的工作,因为在你的代码没什么好说的,可以“工作”呢。 在当前时刻你的代码只是编译,但它不会做任何事情。 提供代码,将尝试展现多态行为 - 然后我们会看到无论是“工作”或没有。
作为实现二元运营商成员函数...这事已经覆盖超过一次已经多。 作为成员函数实现二元运算符的行为“不对称”关于隐含参数转换。 这就是为什么它通常是一个更好的主意来实现对称的二元运算符作为独立的功能。