【问题标题】:C++ inheritance of overloading of comparison and output operators比较和输出运算符重载的 C++ 继承
【发布时间】:2021-09-05 22:59:11
【问题描述】:

我有一些带有几何图形的 C++ 类,我需要重载比较运算符(例如 ><= 等)和输出运算符 <<当我需要打印或比较这些类的任何实例时,我会参考它们区域的值(我使用getArea() 得到)。

我试图将这些运算符重载放在父类 GeometricShape 中,但我遇到了各种编译器错误,这对我来说没有多大意义。

如果我将运算符重载放在每个子类中,它可以正常工作,但它非常丑陋且不理想(大量代码重复)。

如何删除此代码重复并将运算符重载移动到父类?

using namespace std;

#include <iostream>
#include <stdlib.h>
#include <math.h>

class GeometricShape
{
    public:

    double getArea();
};

class Poligon : public GeometricShape
{
    protected:

    double base;
    double height;

    public:

    Poligon(double base, double height) : base(base), height(height) {}
    Poligon(float base, float height) : Poligon(double(base), double(height)) {}
    Poligon(int base, int height) : Poligon(double(base), double(height)) {}

    double getBase()
    {
        return this->base;
    }

    double getHeight()
    {
        return this->height;
    }

    void setBase(double b)
    {
        this->base = b;
    }

    void setHeight(double a)
    {
        this->height = a;
    }
};


class Rectangle : public Poligon
{
    public:

    Rectangle(double base, double height) : Poligon(base, height) {}
    Rectangle(float base, float height) : Poligon(base, height) {}
    Rectangle(int base, int height) : Poligon(base, height) {}

    double getArea()
    {
        return base * height;
    }

    // HOW TO MOVE THIS CODE INTO GeometricShape and reuse it???
    friend ostream& operator<<(ostream& out, Rectangle &obj)
    {
        out << obj.getArea();
        return out;
    }
    friend bool operator==(Rectangle &obj1, Rectangle &obj2)
    {
        return obj1.getArea() == obj2.getArea();
    }
    friend bool operator>(Rectangle &obj1, Rectangle &obj2)
    {
        return obj1.getArea() > obj2.getArea();
    }
    friend bool operator<(Rectangle &obj1, Rectangle &obj2)
    {
        return obj1.getArea() < obj2.getArea();
    }
    friend bool operator <= (Rectangle &obj1, Rectangle &obj2)
    {
        return obj1.getArea() <= obj2.getArea();
    }
    friend bool operator >= (Rectangle &obj1, Rectangle &obj2)
    {
        return obj1.getArea() >= obj2.getArea();
    }
};

class Triangle : public Poligon
{
    public:

    Triangle(double base, double height) : Poligon(base, height) {}
    Triangle(float base, float height) : Poligon(base, height) {}
    Triangle(int base, int height) : Poligon(base, height) {}

    double getArea()
    {
        return (base * height)/2;
    }
    
    // HOW TO MOVE THIS CODE INTO GeometricShape and reuse it???
    friend ostream& operator<<(ostream& out, Triangle &obj)
    {
        out << obj.getArea();
        return out;
    }
    friend bool operator==(Triangle &obj1, Triangle &obj2)
    {
        return obj1.getArea() == obj2.getArea();
    }
    friend bool operator>(Triangle &obj1, Triangle &obj2)
    {
        return obj1.getArea() > obj2.getArea();
    }
    friend bool operator<(Triangle &obj1, Triangle &obj2)
    {
        return obj1.getArea() < obj2.getArea();
    }
    friend bool operator <= (Triangle &obj1, Triangle &obj2)
    {
        return obj1.getArea() <= obj2.getArea();
    }
    friend bool operator >= (Triangle &obj1, Triangle &obj2)
    {
        return obj1.getArea() >= obj2.getArea();
    }
};

class Circle : public GeometricShape
{
    double radius;

    public:

    Circle(double radius) : radius(radius) {}

    double getArea()
    {
        return (radius * radius) * M_PI;
    }

    double getRadius()
    {
        return this->radius;
    }

    void setRadius(double r)
    {
        this->radius = r;
    }

    // HOW TO MOVE THIS CODE INTO GeometricShape and reuse it???
    friend ostream& operator<<(ostream& out, Circle &obj)
    {
        out << obj.getArea();
        return out;
    }
    friend bool operator==(Circle &obj1, Circle &obj2)
    {
        return obj1.getArea() == obj2.getArea();
    }
    friend bool operator>(Circle &obj1, Circle &obj2)
    {
        return obj1.getArea() > obj2.getArea();
    }
    friend bool operator<(Circle &obj1, Circle &obj2)
    {
        return obj1.getArea() < obj2.getArea();
    }
    friend bool operator <= (Circle &obj1, Circle &obj2)
    {
        return obj1.getArea() <= obj2.getArea();
    }
    friend bool operator >= (Circle &obj1, Circle &obj2)
    {
        return obj1.getArea() >= obj2.getArea();
    }
};

【问题讨论】:

  • getArea 应该是虚拟的,并且操作符应该基于GeomatricShape(并成为其好友)。上述相同的派生(即PoligonRectangle 等)然后提供getArea 的虚拟覆盖。我强烈怀疑classic slicing problem 会出现在你的未来,顺便说一句,如果你打算收集这些东西。
  • “如何将此代码移动到 GeometricShape” → 不要。将其移出并使其成为独立功能。
  • 缺少const BTW。
  • 如果您显示不能与编译器错误消息一起工作的代码,这会更容易。这对您来说没有意义,但编译器错误消息包含很多有用的信息,我们可以帮助您理解它。
  • 附带说明,了解您的用例也会有所帮助。你甚至可能一开始就不需要继承。

标签: c++ inheritance operator-overloading ostream comparison-operators


【解决方案1】:

这段代码有很多问题需要修复。

外部独立的operator&lt; 应该不会出现编译错误:

bool operator<(GeometricShape& s1, GeometricShape& s2) {
    return s1.getArea() < s2.getArea();
}
  1. 您应该将 operator
  2. getArea 应在 GeometricShape 中标记为虚拟。所有子类也应该用override 标记方法。否则,将调用 GeometricShape 中的 getArea。
  3. 在几何形状中,您应该将getArea() 函数设为纯虚函数。
  4. 为确保派生类的对象调用了正确的析构函数,应将 GeometricShape 中的析构函数标记为虚拟。

这将使您的方法签名看起来像:

对于几何形状:

virtual double getArea() const = 0;

对于派生类:

double getArea() const override;

编辑:cmets 中有很多关于如何改进这段代码的建议。我已经尽力在这里总结了。

【讨论】:

  • 2.在基础中将其声明为virtual 就足够了。 3. 我完全不明白你的意思。
  • operator&lt;&lt; 有点奇怪,bool operator&lt;&lt;(GeometricShape&amp; s1, GeometricShape&amp; s2) 应该是std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out, GeometricShape const&amp; gs) EDIT1:或者您可能想要一个operator&lt; EDIT2:在这些输入上仍然需要const
  • 我认为您将 &lt;&lt;&lt; 混淆
  • @RajatJain 在覆盖基类方法的方法上使用override 是一种很好的做法,然后添加virtual 不会添加任何其他信息
  • 另外,GeometricShapevirtual ~GeometricShape() = default;中应该有一个虚拟析构函数
猜你喜欢
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
  • 2021-02-05
相关资源
最近更新 更多