简体   繁体   中英

C++ How do I create a dynamic array of objects inherited from an abstract class?

My task specifically states that I have to create a random array of Squares and Triangles, that are inherited from an abstract class Figure, and then I have to print out their square area. Coming from C#, I thought I'd be off with an array of objects, but they do not exist in C++. I'm not allowed to use anything like vectors. Making a dynamic array of Figure doesn't work because apparently it never works with abstract classes. What should I do? Please, keep it simplified if possible.

Here's my current code. Very basic, but it's here just to show what I'm trying to do.

#include <iostream>
#include <stdlib.h>

using namespace std;

class Figure
{
    public:
        virtual double square() = 0;
};

class Square : public Figure
{
    public:
        double side;

        double square()
        {
            return side * side;
        }
};

class Triangle : public Figure
{
    public:
        double height;
        double side;

        double square()
        {
            return 0.5 * side * height;
        }
};

void main()
{
    int size = 20;
    Figure *dyn_arr = new Figure[size]; // this doesn't work
    //Also I have to fill it somehow too...
    for (int i = 0; i < size; i++) cout << Figure.square(); //this doesn't    work either
}

Figure *dyn_arr = new Figure[size]; // this doesn't work

It doesn't work because we cannot create an array of Figure s because of the pure virtual function. We wouldn't want to create a Figure by itself in any case. We only want to create either a Square or a Triangle and their sizes may differ. So there is no way to allocate the memory when the array is created.

You could create an array of pointers (size is known at compile time) and then iterate over that:

auto dyn_arr = new Figure*[size];
// auto in the above context becomes Figure** (pointer to a pointer)
for(int i = 0; i < size; i++) 
    cout << dyn_arr[i]->square();

Please keep in mind that arrays and pointers used this way is prone to errors. Far better to use std::make_unique and std::vector .

Here is one way to randomly create the objects:

Figure* go_figure()
{
    std::uniform_int_distribution<int> ud{0,1};
    static std::random_device rd{};
    switch(ud(rd))
    {
        case 0: return new Square{};
        case 1: return new Triangle{};
    }
}

int main()
{
    int size = 20;
    auto dyn_arr = new Figure*[size];
    for(int i = 0; i < size; i++)
        dyn_arr[i] = go_figure();
    for(int i = 0; i < size; i++) 
        cout << dyn_arr[i]->square();
    for(int i = 0; i < size; i++) 
        delete dyn_arr[i];
    delete[] dyn_arr;
}

Firstly main must return int . Then you need to create an array of pointers which will show to abstract class Figure .

Figure **dyn_arr = new Figure*[size];

Then if you want to add a new object of the derived class you are adding simply like this.

dyn_arr[0] = new Triangle(); --> this will create new object which will return the address of that object, and your array is actually array of pointers.

Finnaly if you want to call the function square from any class you can do that like this.

dyn_arr[0]->square();

ps If you don't have at least a little experience with pointers this can be confusing.

You can create a list of generated functions to select from, to create dynamically allocated objects. Using a rng you can then randomly select from the list of generated functions to call, in order to fill out an array of unique_ptr<Figure> s.

Example using std::deque instead of std::vector :

template<typename T>
Figure* Create() { return new T(); }

std::function<Figure*(void)> createFunctions [] = {
    Create<Square>
   ,Create<Triangle>
};

int main()
{
    std::deque<std::unique_ptr<Figure>> shapes;
    std::mt19937 rng;
    rng.seed(std::random_device()());
    std::uniform_int_distribution<std::mt19937::result_type> idxSel(0,1);
    for(int i = 0; i < 20; ++i)
    {
        shapes.emplace_back(createFunctions[idxSel(rng)]());
    }
}

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