如何在C++中制作可比类

How to make Comparable Class in C++

本文关键字:C++      更新时间:2023-10-16

我想用C++做一个接口。如何在运算符重载语句中获取 op2.radius 值?我希望可比类可以用于其他类,例如矩形、线条等。

#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;
}

您需要进行向下投射,没有通用的方法来获取半径。
如果您确定传递给它的唯一对象是 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;
    }
}

我们可以利用奇怪的重复模板模式 (CRTP) 将我们的派生类传递到 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} 
}

演示

最重要的是,请注意Circle类中operator<operator>的专业化:

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

它们直接采用另一个Circle作为参数。

您可以像使用 operator== 定义一个Equatable抽象类。如果您的派生类(例如圆、数字、日期)可以同时比较排序和相等,则可以使用多重继承来继承ComparableEquatable

给读者的练习:实现(接口)所有6个关系运算符(<>==!=<=>= Circle),比较其半径。可能的解决方案在这里:演示

我们不会在C++中制作像Comparable这样的类。C++不是Java;它有自己的成语。您在标准库中看不到任何类似于Comparable的东西,这强烈暗示您试图朝着错误的方向前进。

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

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

相关文章:
  • 没有找到相关文章