简体   繁体   中英

Making a vector of base class pointers and pass Derived class objects to it (Polymorphism)

I'm trying to implement a menu for my Shape program. I've implemented all of the shapes classes. Two are deriving straight from the abstract class "Shape", and two others are deriving from a class called "Polygon" which derives from "Shape" as shown bellow:

Shape -> Polygon -> Rectangle, Triangle
  `-> Circle, Arrow

In my menu class, I want to create some sort of an array that can contain the pointers to the objects and with the type of the base class "Shape". But I'm not sure how to do it properly and in a way which will work for all of my shapes, because 2 of my classes aren't deriving from "Shape" directly.

This is my menu class:

class Menu
{
protected:
    //array of derived objects 
public:

    Menu();
    ~Menu();

    // more functions..
    void addShape(Shape& shape);
    void deleteAllShapes();
    void deleteShape(Shape& shape);
    void printDetails(Shape& shape);
private:
    Canvas _canvas; //Ignore, I use this program to eventually draw this objects to a cool GUI
};

And in the function "addShape(Shape& shape);", Which I want to use to add each given shape to my array. How can I implement the addition of new objects to it? And also, how can I check if the given object is deriving from "Polygon" or not? Because if so then I need to call the member functions differently as far as I understand.

I see that you have an array in Menu, let's say:

Shape* myshapes[10];

The shapes can be Rectangles, Triangles, Circles etc. What you want is to be able to use the Menu's printDetails() method like this:

    void printDetails()
    {
        for(int i = 0; i < size; i++)
        {
            cout << "Index " << i << " has " << myshapes[i]->getShapeName() << endl;
        }
    }

The getShapeName() will return a string, eg "Rectangle" if it is Rectangle. You will be able to do this with the help of pure virtual function. The pure virtual function must be in the abstract class Shape, which has:

virtual string getShapeName() = 0; //pure virtual

It means that we are expecting a definition for this function in the derived class. This way you will be able to use getShapeName() method using the Shape pointers in the shapes array, which will tell you whether the shape is Rectangle, Triangle, or Circle etc.

class Shape
{
    public:
    virtual string getShapeName() = 0;
};

class Circle : public Shape
{
    private:
    int radius;

    public:
    Circle(int r) { radius = r; cout << "Circle created!\n"; }
    string getShapeName() { return "Circle"; }
};

class Arrow : public Shape
{
    private:
    int length;

    public:
    Arrow(int l) { length = l; cout << "Arrow created!\n"; }
    string getShapeName() { return "Arrow"; }
};

class Polygon : public Shape
{
    public:
    virtual string getShapeName() = 0;
};

class Triangle : public Polygon
{
    private:
    int x, y, z;

    public:
    Triangle(int a, int b, int c) { x = a; y = b; z = c; cout << "Triangle created!\n"; }
    string getShapeName() { return "Triangle"; }
};

class Rectangle : public Polygon
{
    private:
    int length;
    int width;

    public:
    Rectangle(int l, int w){ length = l; width = w; cout << "Rectangle created!\n"; }
    string getShapeName() { return "Rectangle"; }
};

To implement the addShape() method you can do this:

void addShape(Shape &shape)
{
    myshapes[count] = &shape;
    count++;
}

Also, keep in mind to pass the Shape by reference or by using pointer, in the addShape() method. I hope this helps... Best of luck :-)

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