2014-10-02 69 views
0

我正在经历从Java到C++的转换,并试图编写一个简单的程序。调用超类方法运算符==

有一个超Animal具有以下inteface:

class Animal 
{ 
public: 
    Animal(int a, std::string n); 

    bool operator==(Animal a); 
private: 
    int age; 
    std::string name; 
}; 

而且它的子类Dog

class Dog : public Animal 
{ 
public: 
    Dog(int a, std::string n, double w); 

    bool operator==(Dog d); 
private: 
    double weight; 

}; 

我的问题是关于狗的operator==方法,其中比较2只狗。

动物的operator==低于。

bool Animal::operator==(Animal a) //overriding of operator == 
{ 
return (age==a.age) && (name==a.name); 
} 

现在我想用Animal的方法编写狗的版本。

就像我在Java中做到:

boolean equals(Dog d){ 
    return (super.equals(d)) && (this.name==d.name); 
} 

我需要的是(super.equals(d)) C++的等价物。如果它是一个正常名称的方法,它会很容易(Animal :: equals(d)),但我不知道如何为operator ==操作,它有不同的语法。

+2

使用标准符合签名:布尔运算符==(const Animal&a)const;' – 2014-10-02 18:15:00

+0

你知道如何在父类中调用普通函数吗?当你弄明白的时候,你只需要记住'operator =='只是一个普通的成员函数。 – 2014-10-02 18:16:06

+0

@crashmstr:因为他说他已经知道如何使用'Animal :: equals(d)'了,所以不是这样。 – 2014-10-02 18:16:49

回答

6

这其实非常容易:

return Animal::operator==(d) && name==d.name; 

之所以使用超类的名称,而不是super的是,在C++中,你可以有多个超类,所以你必须要清楚你要哪一个。

或者,你可以通过使用它调用它的过载:

return ((Animal&)*this)==d && name==d.name; 

因为在这种情况下,paramters到operator==将是一个Animal&Dog&,那么它无法比拟Dog::operator==(Dog d),所以使用Animal::operator==(Animal a)代替。

注意:您的签名非常不寻常。相反,使用其中的一个:

bool operator==(const Animal& a) const; 
friend bool operator==(const Animal& left, const Animal& right); 

这些不要让动物的副本每次比较的时间,可以比较const动物。

+0

谢谢,我应该尝试添加这样的“运算符”,但我认为它不会工作,因为我通过做(object1 == object2)来调用方法。 – 2014-10-02 18:25:35

0

您可以使用详细注释呼叫话务员:

operator==(const Dog& dog) { return Animal::operator==(dog) && weight==dog.weight; } 
+0

'weight'是'double'类型,你确定你的代码好吗? – 2014-10-02 18:25:15

+0

@PiotrS。为什么不?它取决于实际值的来源,但如果它们基本上是不变的,并且来自人类的输入,那么测试就很好。 – 2014-10-02 18:26:54

+0

@JamesKanze:例如消除你提到的这种“依赖性”?让他们改变? – 2014-10-02 18:28:57

0

你的Java equals的直接等同是:

bool Dog::operator==(Dog d) 
{ 
    return Animal::operator==(d) && weight == d.weight; 
} 

但我不知道这是你真正想要的。对于初学者, 你正在通过复制参数,这意味着你的 比较副本。特别是,当您拨打 Animal::operator==时,您将通过Animal部分 的Dog的副本,而不是完整的对象。班级类型通常是 通过引用传递;参考const如果你不想 修改它们。因此,在底部的签名会是这样 这样的:

bool Animal::operator==(Animal const& other) const 
{ 
    // ... 
} 
Dog

而与此类似。此外,Dog 中的比较运算符可能需要Animal const&,而不是Dog const&。 (在 的Java,equals需要java.lang.Object,永远。)这意味着 是你必须确认它是一个Dog

bool Dog::operator==(Animal const& other) const 
{ 
    return dynamic_cast<Dog const*>(&other) != nullptr 
     && Animal::operator==(other) 
     && weight == other.weight; 
} 

编辑:

正如指出的评论,虽然这解决了 即时语法问题的原始海报,它不是 真的是我们通常这样做的方式。通常的解决办法 是这样的:

class Animal 
{ 
    // If Animal is actually an abstract class (usually the case 
    // in real code), this would be a pure virtual. 
    // Derived classes overriding this function are guaranteed 
    // that other is actually of the same type as they are, 
    // so they can just static_cast it to their type. 
    virtual bool doIsEqual(Animal const& other) const 
    { 
     return true; 
    } 
public: 
    bool isEqual(Animal const& other) 
    { 
     return typeid(*this) == typeid(other) 
      && // ... his local conditions... 
      && doIsEqual(other); 
    } 
}; 

bool operator==(Animal const& lhs, Animal const& rhs) 
{ 
    return lhs.isEqual(rhs); 
} 

bool operator!=(Animal const& lhs, Animal const& rhs) 
{ 
    return !lhs.isEqual(rhs); 
} 

operator==实施和operator!=实际上可以 通过适当的类模板,它 避免了一些样板的继承来完成,如果你有很多的类 其中必须支持==和其他。

+0

如果您拥有* concrete *类的子类,则您的比较方法需要进行一些调整。试试'动物(1,“筷子”);狗b(1,“筷子”,30); (a == b)==(b == a)'。 – 2014-10-02 18:43:23

+0

@ n.m。是。在实践中,我会在'Animal'中使用一个虚拟的'isEqual'函数,其中包含自由函数'operator =='和'operator!=',这个函数仅用于'Animal'。 (但是,我仍然怀疑继承具体类,除非我使用模板方法模式,我认为OP实际上只是创建了一个人为的例子来演示他提出的语法问题;这种类型的层次结构并没有实现, t出现在编写良好的代码中。) – 2014-10-03 09:23:33

+0

比较typeid有它自己的陷阱。假设有人发布具有各种形状类的几何图形库,并且其他人将其扩展到绘图库,添加颜色和其他绘图样式。现在,彩色形状永远不会与普通的无色形状相同。但几何图书馆不关心颜色,它需要几何平等。同样,不同颜色的形状总是不相等的,这对于绘制操作来说是可以的,但会破坏依赖于几何比较的几何操作。 TL; DR == ==在层次结构中是危险的,但是你看它。 – 2014-10-03 09:43:55