如何在C ++中制作Comparable Class

时间:2014-11-24 05:54:46

标签: c++

我想在C ++中创建一个接口。 如何在运算符重载语句中获取op2.radius值? 我希望Comparable Class可以用于其他如Rectangle,Line等。

#include <iostream>
using namespace std;

class Comparable {
      public:
             virtual bool operator > (Comparable& op2)=0;
             //virtual bool operator < (Comparable& op2)=0;
             //virtual bool operator == (Comparable& op2)=0;
};

class Circle : public Comparable {
      int radius;
      public:
             Circle(int radius=1) { this->radius = radius; }
             int getRadius() { return radius; }
             bool operator > (Comparable& op2)
             {
                  if (radius > op2.radius) // <-- here!
                  return true;
                  else
                  return false;
             }

};

template <class T>
T bigger(T a, T b){
           if (a > b) return a;
           else
           return b;
}

void main()
{
    Circle waffle(10), pizza(20), y;
    y = bigger(waffle, pizza);
    cout << "the bigger one is " << y.getRadius() << endl;
}

3 个答案:

答案 0 :(得分:3)

我们不会在C ++中创建类似Comparable的类。 C ++不是Java;它有自己的成语。您在标准库中看不到任何类似Comparable的内容,这是您尝试向错误方向移动的强烈暗示。

在您的特定情况下,不清楚bigger应该做什么。你想比较圆和三角形吗?如果不是,则圆和三角形都不属于Comparable接口。如果有,怎么样?按地区划分? (如果是这样,那么您可以使用virtual double area()和非虚拟bool bigger()来调用它。圆圈和球体怎么样?你可以比较两个圆圈或两个球体,但是将一个圆圈与一个球体进行比较只是没有多大意义。

同时拥有Circle::biggerSphere::bigger没有任何问题,但它们不能同时覆盖某个假设的公共基类或接口中的同一个虚函数,即使你能以某种方式发明一个该功能的工作签名。

答案 1 :(得分:2)

你需要做一个向下投射,没有通用的方法来获得半径。
如果你确定传递给它的唯一对象是Circle类型,那么静态转换就足够了。
如果不是这种情况,那么尝试使用dynamic_cast来检查它是否是Circle对象。如果失败则返回false。
注意:dynamic_cast会降低性能。

bool operator > (Comparable& op2)
{
    Circle* foo = dynamic_cast<Circle*>(&op2);
    if (foo && (radius > foo->getRadius()))
    {
        return true;
    }
    else
    {
        return false;
    }
}

答案 2 :(得分:0)

我们可以利用curiously recurring template pattern将派生类传递到Comparable类中。这样,就无需强制转换参数。

#include <iostream>


template<typename T>
class Comparable {
public:
    virtual bool operator< (T const& other) const =0;
    virtual bool operator> (T const& other) const =0;
};

class Circle : public Comparable<Circle> {    //  note Circle itself is passed as a template parameter
public:
    Circle(int radius = 1) : radius(radius) {}

    bool operator< (Circle const& other) const { return this->radius < other.radius; }
    bool operator> (Circle const& other) const { return this->radius > other.radius; }

    friend std::ostream& operator<< (std::ostream& os, Circle const& c) {
        os << "Circle{.radius=" << c.radius << "}";
        return os;
    }

private:
    int radius;
};


int main()
{
    Circle c1{5};
    Circle c2{7};
    std::cout << std::boolalpha;
    std::cout << (c1 < c2) << std::endl;            //  true
    std::cout << std::max(c1, c2) << std::endl;     //  Circle{.radius=7} 
}

Demo

bool operator< (Circle const& other) const { return this->radius < other.radius; }
bool operator> (Circle const& other) const { return this->radius > other.radius; }

最重要的是,请注意operator<类中operator>Circle的专业化直接将另一个Circle作为参数。

您可以使用Equatable类似地定义operator==抽象类。如果可以比较派生类(例如Circle)的排序和相等性,则可以使用多重继承来继承ComparableEquatable