【问题标题】:Use virtual function to calculate area for different shapes C++使用虚函数计算不同形状的面积 C++
【发布时间】:2020-11-14 10:02:32
【问题描述】:
#include <iostream>
#include <fstream>
using namespace std;

class Shape
{
  public:
    string name;
    double width, height, radius;
  public:
    void set_data (double a, double b)
    {
        width = a;
        height = b;
    }
    virtual double area() = 0;
};

class Rectangle: public Shape
{
public:
    double area ()
    {
        return (width * height);
    }
};

class Triangle: public Shape
{
public:
    double area ()
    {
        return (width * height)/2;
    }
};

class Circle : public Shape
{
  public:
    double area ()
    {
        return 3.1415 * (radius * radius);
    }
};

int main()
{
    int N;
    cin >> N;

    Rectangle Rect;
    Triangle Tri;
    Circle Circ;
    string* S = new string[N];

    if(N == 1) {
      cin >> Rect.name >> Rect.height >> Rect.width;
      cout << Rect.area();

      return 0;
    } 
    else
{
    for(int i = 0; i < N; i++)
    {
        cin >> S[i];

        if(S[i] == "Rectangle")
        {
            cin >> Rect.height;
            cin >> Rect.width;
        }
         else if(S[i] == "Triangle")
             {
                 cin >> Tri.height;
                 cin >> Tri.width;
             }
             else if(S[i] == "Circle")
                  {
                      cin >> Circ.radius;
                  } 

    }
}
    cout << Rect.area() << " " << Tri.area() << " " << Circ.area();

  delete [] S;

    return 0;
}

代码在测试 1 和测试 2 中运行良好,但在测试 3 中出现错误... 我需要输入 N 个数字(形状的计数)并按升序显示在输出所有区域中...

例如:

====== 测试#1 =======

输入:

1

矩形 4 3

输出: 12

真正的答案: 12

好的!

====== 测试#2 =======

输入:

3

三角形 4 6

矩形 2 3

第 3 圈

输出: 6 12 28.2735

真正的答案: 6 12 28.2735

好的!

====== 测试#3 =======

输入:

5

三角形 4 6

矩形 2 3

第 4 圈

三角形 7 11

三角形 3 5

输出: 6 7.5 50.264

真正的答案: 6 7.5 12 38.5 50.264

错误!

请告诉我,为什么我的代码不起作用?

【问题讨论】:

  • 好吗?你知道如何让程序对事物进行排序吗?
  • 在容器中存储指针或引用(例如std::vector),并将std::sort与适当的lambda(例如[](Shape&amp; a, Shape&amp; b) { return a.area() &lt; b.area(); })一起使用?顺便说一句,更好的签名:virtual double area() const = 0;。不要忘记 override 关键字。
  • 不知道怎么解决
  • 另外,从设计的角度来看,抽象形状不应该有宽度、高度或半径。这些概念不适用于此级别。你的矩形没有半径,你的圆没有宽度和高度(本身)。

标签: c++ function class inheritance virtual


【解决方案1】:

基本上,cmets 指出了主要问题,但我想展示抽象的具体设计:

让我们从形状属性类的concept 开始:

class shape_property {};

template <typename T>
concept ShapeProperty = std::is_base_of_v<shape_property, T>;

对于shape 类(接受形状属性作为模板参数):

template <ShapeProperty ...Properties>
class shape : virtual public Properties... {
public:
    explicit shape(std::string name) : name(std::move(name)) {}
    virtual ~shape() = default;

    [[nodiscard]] std::string get_name() const { return name; }

    virtual void input_data() = 0;
    [[nodiscard]] virtual double area() const = 0;

protected:
    std::string name;
};

属性示例:

class width_shape_property : shape_property {
public:
    [[nodiscard]] double get_width() const { return width; }
    void set_width(double width) { this->width = width; }

protected:
    double width;
};

class height_shape_property : shape_property {
public:
    [[nodiscard]] double get_height() const { return height; }
    void set_height(double height) { this->height = height; }

protected:
    double height;
};

class radios_shape_property : shape_property {
public:
    [[nodiscard]] double get_radios() const { return radios; }
    void set_radios(double radios) { this->radios = radios; }

protected:
    double radios;
};

形状示例:

class rectangle : public shape<width_shape_property, height_shape_property> {
public:
    rectangle() : shape("Rectangle") {}

    void input_data() override {
        double width, height;
        std::cout << "Enter width & height:" << std::endl;
        std::cin >> width >> height;
        set_width(width);
        set_height(height);
    }

    [[nodiscard]] double area() const override {
        return width * height;
    }
};

class triangle : public shape<width_shape_property, height_shape_property> {
public:
    triangle() : shape("Triangle") {}

    void input_data() override {
        double width, height;
        std::cout << "Enter width & height:" << std::endl;
        std::cin >> width >> height;
        set_width(width);
        set_height(height);
    }

    [[nodiscard]] double area() const override {
        return (width * height) / 2;
    }
};

class circle : public shape<radios_shape_property> {
public:
    circle() : shape("Circle") {}

    void input_data() override {
        double radios;
        std::cout << "Enter radios:" << std::endl;
        std::cin >> radios;
        set_radios(radios);
    }

    [[nodiscard]] double area() const override {
        return M_PI * radios * radios;
    }
};

现在,为了将形状包含在单个容器中,我使用了 @MarkGarcia solution,它基于 @SeanParent talk "Inheritance Is The Base Class Of Evil" 进行了一些小的修改:

class virtual_base {
public:
    template<typename T>
    virtual_base(T &obj) : m_obj(std::make_shared<impl<T>>(obj)) {}

    void input_data() {
        m_obj->input_data();
    }

    [[nodiscard]] double area() const {
        return m_obj->area();
    }

private:
    class interface {
    public:
        virtual ~interface() = default;
        virtual void input_data() = 0;
        [[nodiscard]] virtual double area() const = 0;
    };

    template<typename T>
    class impl : public interface {
        T& m_impl_obj;

    public:
        explicit impl(T& impl_obj) : m_impl_obj(impl_obj) {}

        void input_data() override {
            m_impl_obj.input_data();
        }

        [[nodiscard]] double area() const override {
            return m_impl_obj.area();
        }
    };

    std::shared_ptr<interface> m_obj;
};

结果:

int main() {
    std::vector<virtual_base> shapes;

    rectangle r;
    triangle t;
    circle c;

    shapes.emplace_back(r);
    shapes.emplace_back(t);
    shapes.emplace_back(c);

    for (auto &shape : shapes) {
        shape.input_data();
        std::cout << shape.area() << std::endl;
    }

    r.set_width(10);
    std::cout << shapes[0].area() << std::endl;

    return EXIT_SUCCESS;
}

必需的标题:

#include <iostream>
#include <vector>
#include <memory>
#include <math.h>

For the github repository of the updated code.

【讨论】:

  • 不错的 flex,兄弟。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-07
  • 2013-09-27
  • 2018-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多