Stack Overflow Asked by Var_the_an on December 30, 2021
#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;
}
the code works well in the Test 1 and Test 2, but in Test 3 give an error…
im need to input N number(count of Shapes) and display in Output all areas in ascending order…
For Example:
====== TEST #1 =======
Input:
1
Rectangle 4 3
Output:
12
The True Answer:
12
OK!
====== TEST #2 =======
Input:
3
Triangle 4 6
Rectangle 2 3
Circle 3
Output:
6 12 28.2735
The True Answer:
6 12 28.2735
OK!
====== TEST #3 =======
Input:
5
Triangle 4 6
Rectangle 2 3
Circle 4
Triangle 7 11
Triangle 3 5
Output:
6 7.5 50.264
The True Answer:
6 7.5 12 38.5 50.264
Error!
Please tell me, why my code is not working?
Basically, the comments pointed the main issues, but I want to show a specific design for the abstraction:
Let's start with a concept
for a shape property classes:
class shape_property {};
template <typename T>
concept ShapeProperty = std::is_base_of_v<shape_property, T>;
For the shape
class (which accepts shape properties as template parameters):
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;
};
Properties examples:
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;
};
Shape examples:
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;
}
};
Now, to contain the shapes in a single container, I used @MarkGarcia solution, which based on @SeanParent talk "Inheritance Is The Base Class Of Evil" with some minor modifications:
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;
};
And the result:
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;
}
Required headers:
#include <iostream>
#include <vector>
#include <memory>
#include <math.h>
Answered by CoralK on December 30, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP