Dynamic memory management for a class hierarchy of geometric shapes The task was to write function that compare areas of two random generated geometric shapes (circle, square, rectangle) using base class with virtual function.

Am I doing it right in terms of memory management?
Will my figures generated inside generateRandomShape() by new Square() etc. last in memory outside this function untill I manually delete them?

#include &lt;iostream&gt;
#include &lt;cstdlib&gt;
#include &lt;ctime&gt;
#define _USE_MATH_DEFINES
#include &lt;cmath&gt;
#include &lt;vector&gt;

#define M_PI       3.14159265358979323846

class Shape {
public:
    virtual float area() = 0;
};

class Square : public Shape {
protected:
    float sideA;

public:
    Square(float sideA) : sideA(sideA) {}
    float area() { return sideA * sideA; }
};

class Circle : public Shape {
protected:
    float radius;

public:
    Circle(float radius) : radius(radius) {}
    float area() { return M_PI * radius * radius; }
};

class Rectangle : public Shape {
protected:
    float sideA, sideB;

public:
    Rectangle(float sideA, float sideB) : sideA(sideA), sideB(sideB) {}
    float area() { return sideA * sideB; }
};

void compareAreasOffigures(Shape* a, Shape* b){
    if (a-&gt;area() == b-&gt;area()) {
        std::cout &lt;&lt; "Areas of two shapes are equal." &lt;&lt; std::endl;
    }
    else if (a-&gt;area() &gt; b-&gt;area()) {
        std::cout &lt;&lt; "Area of first Shape is bigger." &lt;&lt; std::endl;
    }
    else {
        std::cout &lt;&lt; "Area of second Shape is bigger." &lt;&lt; std::endl;
    }
}

Shape * generateRandomShape() {
    int Shape;
    Shape = rand() % 3;

    switch (Shape)  {

        case 0: {
            int sideA = rand() % 100;
            std::cout &lt;&lt; "Square was generated, side: " &lt;&lt; sideA &lt;&lt; std::endl;
            return new Square(sideA);
            break;
        }

        case 1: {
            int sideA = rand() % 100;
            int sideB = rand() % 100;
            std::cout &lt;&lt; "Rectangle was generated, side A: " &lt;&lt; sideA &lt;&lt; " side B: " &lt;&lt; sideB &lt;&lt; std::endl;
            return new Rectangle(sideA, sideB);
            break;
        }
        case 2: {
            float radius = rand() % 100;
            std::cout &lt;&lt; "Circle was generated, radius: " &lt;&lt; radius &lt;&lt; std::endl;
            return new Circle(radius);
            break;
        }
        default: return NULL;
    }
}

int main(void){

    srand(time(0));

    std::vector&lt;Shape*&gt; shapes;

    shapes.push_back(generateRandomShape());
    shapes.push_back(generateRandomShape());

    compareAreasOffigures(shapes[0], shapes[1]);

    for (auto v : shapes) { delete v; } //cleanup
    shapes.clear();

    return EXIT_SUCCESS;
}
Dynamic Memory Management


  Am I doing it right in terms of memory menagment?


You should rather use smart pointers to store the Shape instances in the vector:

 std::vector&lt;std::unique_ptr&lt;Shape&gt;&gt; shapes;


and 

 std::unique_ptr&lt;Shape&gt; generateRandomShape() {
     int Shape; // Take care! Some compilers don't like it if variables 
                // arenamed the same as defined types
     Shape = rand() % 3;

         switch (Shape)  {
         case 0: {
             int sideA = rand() % 100;
             std::cout &lt;&lt; "Square was generated, side: " &lt;&lt; sideA &lt;&lt; std::endl;
             return std::make_unique&lt;Square&gt;(sideA);                 
         } break; // Put the break out side the case scope block
         case 1: {
             int sideA = rand() % 100;
             int sideB = rand() % 100;
             std::cout &lt;&lt; "Rectangle was generated, side A: " &lt;&lt; sideA &lt;&lt; " side B: " &lt;&lt; sideB &lt;&lt; std::endl;
             return std::make_unique&lt;Rectangle&gt;(sideA, sideB);
         } break;
         // ...
     }
     // No need for the default case
     return std::unique_ptr&lt;Shape&gt;();
}


thus you can completetly omit

 for (auto v : shapes) { delete v; } //cleanup



  Will my figures generated inside generateRandomShape() by new Square() etc. last in memory outside this function untill I manually delete them?


Yes, but handling new and delete on your own turns out to be error prone and semantically unclear.

Use virtual destructors for dynamic polymorphic inheritance

For formal correctness you should declare virtual destructors for your abstract base class and the derived classes

class Shape {
public:
    float area() = 0;
    virtual ~Shape() = default; // &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;
};


This isn't done automatically for compiler generated destructors (see an explanation here).

Use const class members whenever appropriate

Use const whenever appropriate. The area() calculation doesn't change any of the internal states of a Shape instance, so it should be declared as a const member function:

class Shape {
public:
    float area() const = 0;
              // ^^^^^ 
};


This improves your classes to be used in wider contexts, e.g. with temporary class instances.

Also you could rewrite your function signature 

void compareAreasOffigures(Shape* a, Shape* b);


like that then1)

void compareAreasOffigures(const Shape* a, const Shape* b);


or even better

void compareAreasOffigures(const Shape&amp; a, const Shape&amp; b);




Note: Do that as soon as possible in your class designs, adding later is much harder than removing that constraint in a later refactoring or override.

Prefer const variable definitions over using preprocessor macros

Instead of 

 #define M_PI       3.14159265358979323846


rather use 

const double M_PI = 3.14159265358979323846;


or 

constexpr double M_PI = 3.14159265358979323846;


for sake of type safety and clarity.

Don't use srand(), rand() with modern c++

Use a better random number generator than 

srand(time(0));

// ...

rand();


There are various random generators available with the current standard in the numerics library.

Don't use == to compare floating point values

Don't use equality comparison for floating point types like

if (a-&gt;area() == b-&gt;area())


it's unlikely these will be exactly equal.

Rather test against std::numeric_limits::epsilon, there's a comprehensive example in the linked documentation.

Your purpose of using _USE_MATH_DEFINES is unclear and inconsistent

Your use of _USE_MATH_DEFINES and defining M_PI yourself is inconsistent.

The purpose of #define _USE_MATH_DEFINES is to use the predefined constants from cmath or math.h, but you define M_PI yourself anyways.

As mentioned here it should be defined before any of the #include statements to guarantee it works

#define _USE_MATH_DEFINES
#include &lt;iostream&gt;
#include &lt;cstdlib&gt;
#include &lt;ctime&gt;
#include &lt;cmath&gt;
#include &lt;vector&gt;


since you cannot know if any of the other header files already includes cmath or math.h.

The highlight of your solution

After so many points of critique, I want to emphasize one bonus point of your solution:

You weren't trapped by the Square is not a Rectangle confusion and provided unrelated classes for these (same for Circle is not an Ellipse).

Beginners often use inheritance like

class Rectangle {
protected:
    float sideA, sideB;
};

class Square : public Rectangle {
};


and run into trouble to keep the class member variables consistent (here's a more detailed resource).



1As mentioned by @Tamoghna Chowdhury before.