Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare a vector of pointers to objects of a class?

The thing is that I am struggling with making objects of the class Shape. I declare the vector, but then do not know how to connect it to the class Shape and its objects. The code itself has one base class, which is Shape and then two subclasses Circle and Rectancle. The idea of the code is to use a vector in the main function, and have multiple cases for the Circle area and the Rectangle area. This is the code:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Shape
{
public:
    virtual double GetArea() const = 0
    {

    }

private:

};

class Circle : public Shape
{
public:
    Circle(double p, double r) // constructor
    {
        pi = p;
        radius = r;
    }

    Circle() : pi(3.14), radius(0) {} // default constructor

    void SetRadius(double value)
    {
        radius = value;
    }

    double GetRadius() const
    {
        return radius;
    }

    double GetArea()
    {
        double area = pi * radius * radius;
        return area;
    }

private:
    double pi = 3.14;
    double radius;
};

class Rectangle : public Shape
{
public:
    Rectangle(double a, double b) // constructor
    {
        sideA = a;
        sideB = b;
    }

    Rectangle() : sideA(0), sideB(0) {} // default constructor

    void SetSideA(double value)
    {
        sideA = value;
    }

    double getSideA() const
    {
        return sideA;
    }

    void SetSideB(double val)
    {
        sideB = val;
    }

    double getSideB() const
    {
        return sideB;
    }

    double getArea()
    {
        double Area = sideA * sideB;
        return Area;
    }

private:
    double sideA;
    double sideB;
};

int main()
{
    vector<Shape*> shape;
    return 0;
}
like image 408
zaimoff Avatar asked Dec 17 '22 14:12

zaimoff


1 Answers

You want Polymorphism. You just use the constructor of the circle or the rectangle, for example:

vector<Shape*> shape(1);
if(/* case is circle*/)
  shape[0] = new Circle();
else
  shape[0] = new Rectangle();

However, you need remove the definition of the pure virtual method in the base class, since it's inside the class, and only declare it.

Then, you need to implement that method, by using exactly the same prototype, so you need to mark the method in Circle as const too. Same for Rectangle class, where you also did a typo, since the name of the method is "GetArea", not "getArea".


Complete Minimal Working Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Shape
{
public:
    virtual double GetArea() const = 0;
    virtual ~Shape() {};
};

class Circle : public Shape
{
public:
    Circle(double p, double r) // constructor
    {
        pi = p;
        radius = r;
    }

    Circle() : pi(3.14), radius(0) {} // default constructor

    void SetRadius(double value)
    {
        radius = value;
    }

    double GetRadius() const
    {
        return radius;
    }

    double GetArea() const
    {
        double area = pi * radius * radius;
        return area;
    }

private:
    double pi = 3.14;
    double radius;
};

class Rectangle : public Shape
{
public:
    Rectangle(double a, double b) // constructor
    {
        sideA = a;
        sideB = b;
    }

    Rectangle() : sideA(0), sideB(0) {} // default constructor

    void SetSideA(double value)
    {
        sideA = value;
    }

    double getSideA() const
    {
        return sideA;
    }

    void SetSideB(double val)
    {
        sideB = val;
    }

    double getSideB() const
    {
        return sideB;
    }

    double GetArea() const
    {
        double Area = sideA * sideB;
        return Area;
    }

private:
    double sideA;
    double sideB;
};

int main()
{
    vector<Shape*> shape(2);
    shape[0] = new Circle(3.14, 1);
    shape[1] = new Rectangle(2, 3);

    for(auto s : shape)
      std::cout << "Shape area = " << s->GetArea() << endl;

    // When you are done, delete the dynamically allocated memory.
    // You can use smart pointers in order to avoid doing this manually (and maybe forget!)
    delete shape[0];
    delete shape[1];
    return 0;
}

Output:

Shape area = 3.14 Shape area = 6

where the first area is from the circle, and the second area from the rectangle.

I suggest you read: Virtual destructor in polymorphic classes and What is the 'override' keyword in C++ used for?


After doing all this for practice, you should really start using smart pointers, like this for instance std::vector<std::unique_ptr<Shape>> shape;, instead of raw pointers. This way, you won't have to worry about deleting manually dynamically allocated memory.

like image 145
gsamaras Avatar answered Jan 19 '23 01:01

gsamaras