2

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
}
5
  • I'm not allowed to use vectors here. Commented Jul 18, 2017 at 20:21
  • Kind of. It was on my exam last week and I was supposed to do that on paper. I still haven't found out the way to do it, so I had to ask here. Commented Jul 18, 2017 at 20:30
  • @Alucard "I'm not allowed to use vectors here" - That's a stupid and arbitrary requirement. In the real world std::vector is what one would use and one would fill it with smart pointers in most cases, not raw pointers. Commented Jul 18, 2017 at 20:56
  • @JesperJuhl My whole uni is full of stupid and arbitrary requirements. I'm just waiting to get out of it with a diploma and do some real world stuff. Commented Jul 18, 2017 at 21:01
  • @Alucard heh, that reminds me of why I skipped uni 20+ years ago ;) Try a few open source projects on for size while you wait; to gain some "real life" experience. I jumped onto the Linux kernel back in the '90s - taught me a lot - these days I'd probably jump onto a successful C++ library that interrested me and start contributing. Commented Jul 18, 2017 at 21:05

3 Answers 3

4

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();

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

Sign up to request clarification or add additional context in comments.

1 Comment

you should code it using vector and shared_ptr for extra credit
3

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

It doesn't work because we cannot create an array of Figures 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;
}

5 Comments

I'd suggest a vector of smart pointers instead of C-style arrays and raw pointers / manual memory management... That's so 90's-ish ;-)
@JesperJuhl Yes that would be best. The question was about basics.
Wow, that actually works! A couple more questions: 1) I need array filled with random objects. How do I do that? 2) Why just changing Figure *dyn_arr to auto dyn_arr fixed that? What does auto do?
if vectors arent allowed then smart pointer probably arent either. Always depressing to see assignments that require unsafe, old fashioned code. Why not insist on assembler (or even direct hex machine code)
@pm100 That's a good question. 90% of my knowledge comes from books, not sure if lecturers even try. But it's always refreshing to see these pop up.
1

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)]());
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.