0

So currently, I'm working on a C++ practice about OOP using polymorphism. I try to store my derived class objects in a collection through a base class pointer. My base class name is shape. My derived class are rectangular, circle and triangle. This is my main.cpp file, I include all header files I need and I compile this.

#include "rectangular.h"
#include "circle.h"
#include "triangle.h"

int choose(short &i, short &h, shape* shp[]);
int get_shape(short &h, shape* shp[]);

int main()
{
    rectangular rec;
    circle c;
    triangle tr;
    shape* shp[] {&rec, &c, &tr};
    bool flag = true;

    short i {0};
    short h {0};

    return 0;
}

int get_shape(short &h, shape* shp[])
{
    std::cout << "Enter a number to choose shape:\n";
    std::cout << "1. Rectangular\n";
    std::cout << "2. Circle\n";
    std::cout << "3. Triangle\n";
    std::cin >> h;
    short a{0};
    for(shape* shp_ptr : shp) //error appears here
    {
        if(a == h)
        {
            std::cin >> *shp_ptr;
        } else if(a > h)
        {
            break;
        }
        a++;
    }
}

VS code throw a error message: "this range-based 'for' statement requires a suitable "begin" function and none was found"

I tried to google this error and I saw a bunch of solution, but none of them are the same as my problem. Some of them say I need to have an iterator as begin and end, but I don't really know how to do it.

I am a C++ newbie and English is not my mother tongue so I'm sorry if my words make you confuse. I really hope that I'll get help in here.

My base class and derived class code if you need them to test on VS code:

shape.h

#ifndef SHAPE_H
#define SHAPE_H
#include <iostream>
class shape
{
    friend std::ostream& operator<< (std::ostream& out, const shape& p); //declaration. Non-member function
    friend std::istream& operator>> (std::istream& in, shape& p);
public:
    shape() = default;

    //virtual void Input() const = 0;
    virtual double area() const = 0;
    virtual double perimeter() const = 0;

    virtual void ostream_shape(std::ostream& out) const = 0;
    virtual void istream_shape(std::istream& in) = 0;
    ~shape() = default;
};

#endif

shape.cpp

#include "shape.h"

std::ostream& operator<< (std::ostream& out, const shape& p)
{
    p.ostream_shape(out);
    return out;
}

std::istream& operator>> (std::istream& in, shape& p)
{
    p.istream_shape(in);
    return in;
}

rectangular.h

#ifndef RECTANGULAR_H
#define RECTANGULAR_H
#include "shape.h"

class rectangular final : public shape
{
private:
    double length {0};
    double width {0};
public:
    rectangular() = default;
    rectangular(double length, double width) : length(length), width(width) {}

    //void Input() const;

    double area() const override;
    double perimeter() const override;
    void ostream_shape(std::ostream& out) const override;
    void istream_shape(std::istream& in) override;

    ~rectangular() = default;
};

#endif

rectangular.cpp

#include "rectangular.h"
#include <iostream>

double rectangular::area() const
{
    return length * width;
}

double rectangular::perimeter() const
{
    return (length + width) * 2;
}

void rectangular::istream_shape(std::istream& in) 
{
    std::cout << "Enter the rectangular length: "; in >> length;
    std::cin.ignore();
    std::cout << "Enter the rectangular width: "; in >> width;
    std::cin.ignore();
}

void rectangular::ostream_shape(std::ostream& out) const
{
    out << "Length: " << length << "\t Width: " << width << std::endl;
    out << "Area: " << area() << "\tPerimeter: " << perimeter() << std::endl;
}

circle.h

#ifndef CIRCLE_H
#define CIRCLE_H
#include "shape.h"

class circle final : public shape
{
private:
    double r{0};
public:
    circle() = default;
    circle(double r) : r(r) {}

    double area() const override;
    double perimeter() const override;
    void ostream_shape(std::ostream& out) const override;
    void istream_shape(std::istream& in) override;

    ~circle() = default;
};

#endif

circle.cpp

#include "circle.h"

double circle::area() const
{
    return 3.14 * r * r;
}

double circle::perimeter() const
{
    return 2 * 3.14 * r;
}

void circle::istream_shape(std::istream& in)
{
    std::cout << "Enter the circle radius: "; in >> r;
    std::cin.ignore();
}

void circle::ostream_shape(std::ostream& out) const
{   
    out << "Circle radius = " << r << std::endl;
    out << "Area: " << area() << "\tPerimeter: " << perimeter() << std::endl;
}

triangle.h

#ifndef TRIANGLE_H
#define TRIANGLE_H
#include "shape.h"

class triangle final : public shape
{
private:
    double a {0};
    double b {0};
    double c {0};
public:
    triangle() = default;
    triangle(double a, double b, double c) : a(a), b(b), c(c) {}
    
    double area() const override;
    double perimeter() const override;
    void ostream_shape(std::ostream& out) const override;
    void istream_shape(std::istream& in) override;

    ~triangle() = default;
};

#endif

triangle.cpp

#include "triangle.h"

double triangle::area() const
{
    double p = (a + b + c) / 2;
    return p*(p-a)*(p-b)*(p-c);
}

double triangle::perimeter() const
{
    return a + b + c;
}

void triangle::istream_shape(std::istream& in)
{
    std::cout << "Enter the triangle edge a: "; in >> a;
    std::cin.ignore();
    std::cout << "Enter the triangle edge b: "; in >> b;
    std::cin.ignore();
    std::cout << "Enter the triangle edge c: "; in >> c;
    std::cin.ignore();
}

void triangle::ostream_shape(std::ostream& out) const
{
    out << "Triangle edges a= " << a << ", b= " << b << ", c= " << c << std::endl;
    out << "Area: " << area() << "\tPerimeter: " << perimeter() << std::endl;
}
user17732522
  • 53,019
  • 2
  • 56
  • 105
  • 1
    You can't pass arrays to functions like this. `shape* shp[]` in a function parameter actually becomes `shape** shp`. It doesn't know how long the array is. Use `std::vector` or `std::array` instead of raw arrays and this will work as expected. – user17732522 Mar 08 '22 at 10:00
  • @user17732522 thank you so much. I will fix it. – charlotte_1321 Mar 08 '22 at 14:56

0 Answers0