简体   繁体   中英

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;
}

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.

For starters the class Shape must have a virtual destructor

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

    }

    virtual ~Shape() = default;
};

Within the class the member function GetArea is declared with the qualifier const. So in derived classes the overriding function shall also have the qualifier const.

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

and

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

In main you can use the member function push_back to append pointers to objects, For example

std::vector<Shape*> shape;

Shape *p = new Circle( 3.14, 10.0 );

shape.push_back( p );

p = new Rectangle( 10.0, 20.0 );

shape.push_back( p );

Instead of the vector of the type

std::vector<Shape *> shape;

you could use a vector of std::unique_ptr<Shape> . For example

std::vector<std::unique_ptr<SHape>> shape;

In this case you will not need to delete the pointers manually for example by using the standard algorithm std::for_each for the vector.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM