我有一个类的层次结构,我必须重载operator+
和operator-
,以便它生成一个类似的新类型。
Animal * pg = new Pigeon();
Animal * pgone = new Pigeon();
Animal * babypigeon = *pgone + *pg;
其中Animal
是基本类型,Pigeon
是派生类型。我想知道我是否应该重载派生类型的运算符,还是我还需要重载基类型的运算符?
假设将使用基指针创建所有派生类型。
答案 0 :(得分:3)
您的逻辑已关闭,您的程序将无法执行您期望的操作。你在那里添加指针。不会调用+运算符。
你需要像
这样的东西babypigeon = (*pgone) + (*pg);
在这种情况下,您要添加两个动物。所以你的+运算符必须在Animal类中重载。
解决这个问题的方法是从+运算符调用一些虚方法并在那里使用逻辑。
编辑:
class Animal{
//....
virtual Animal plusLogic( const Animal& otherAnimal ) const;
Animal operator + ( const Animal& otherAnimal ) const
{
return this->plusLogic(otherAnimal);
}
}
class Pigeon : public Animal{
//.....
virtual Animal plusLogic( const Animal& otheAnimal ) const;
}
Animal Pigeon::plusLogic (const Animal& otherAnimal) const
{
//logic heree
}
这样,在一个类型为pigeon的Animal上调用+运算符将调用Pigeon类中的函数plusLogic(因为它是虚拟的)。
答案 1 :(得分:2)
你不能这样做 - pgone
和pg
是指针类型,并且不能让运算符为它们重载。你必须有
Animal* baby = *pgone + *pg;
在这种情况下,您需要一个双重调度系统来涵盖所有案例,我也希望您永远不要将这些类型用作值。我希望你也没有太多衍生类型,因为这可能会很快变得讨厌。
答案 2 :(得分:1)
您可能不会为指针类型重载运算符,因此您的代码不应该编译(编辑:问题已被修改且不应编译部分不再有效),
一般运算符重载最好用非多态类型:
a+b+c
)答案 3 :(得分:1)
我看到这种方法有几个非常基本的问题:
对于交配鸽子没有普遍认可的操作员(实际上,使用*
而不是+
表示不是更好吗?),所以这显然 < em>违反first basic rule of operator overloading
虽然@Alexandre开了个玩笑,但他的评论确实有一个好处:而是使用 名称齐全的函数 。
运算符重载是 非常适合值类型 ,而 不适合多态类型 < / strong>即可。交配任何两只动物都没有任何意义 您不能一般性地指定结果的(动态)类型,因为您必须为每个排列创建一个新类型,从而创建甚至新的可能排列,从而导致类型无穷无尽的扩散。 (如果你尝试的话,你也可以跟着动物保护联盟,而且它们可能非常烦人。)
您的示例使用的运算符通过引用获取两个对象,但必须返回指向动态分配对象的指针。这不仅听起来非常错误,而且也是如此
对于初学者:现在你不能再加链(pg1 + pg2 + pg3
,因为加法的结果与它的操作数不是同一类型。这是违反直觉的, 违反了the second basic rule of operator overloading 即可。
我甚至不会触及诸如谁拥有退回物品以及谁负责清理它等问题。
所以结果是: 就是不要这样做。 而且我没有发现这令人惊讶,因为多年来我了解到这是如果您尝试在此类设置中应用运算符重载,则通常会产生结果。