2

I have an assignment and I will list the exercises and then my solution for them as well as the problem that I am nicely asking you to help me understand and resolve it!

  1. The Point class describes a point in a 2D / 3D space and contains

    · x - integer attribute · y - integer attribute · z - integer attribute · Attributes are initialized by default · Class has no default constructor · The class has two constructors: one that requests X and Y and another that requests all values · The class has get and set methods for the three values

Each geometric figure is defined by a given number of corners (the lines that join them define the geometric figure)

  1. The AbstractGeometricFigure class contains

    · Figure type - string attribute · is2D - boolean attribute · number of corners - integer attribute · Corners array - dynamic vector of Point objects · area() - a pure virtual method that determines the area of ​​the geometric figure · perimeter() - pure virtual method that determines the area of ​​the geometric figure · getCorners() - method that displays the corners of the geometric figure using the template (X, Y) for 2D and (X, Y, Z) for 3D · addCorner () - method that adds a new corner

I stumble upon the addCorner() method because I need to create another array to which I will add the new corner. In order to create a dynamic array of type Point class, the compiler is telling me to create the default constructor for the class Point. As you can see above, I am not allowed to do it. How can I create another array that will copy the Corners array, and add at the end of it the new value, without implementing the default constructor of class Point? Even if I don't have to create another array, at the exam it might be possible to have such an exercise, and I want to know , what should I do in case I have a dynamic array of type class, and I am not allowed to implement the default constructor of the class.

Here is my code till this point:

#include<iostream>
#include<string>
using namespace std;

class MySpecialException:public exception
{
public:
    MySpecialException(string msg) :exception(msg.data())
    {

    }
};

class Point
{
    int x=0;
    int y=0;
    int z=0;
public:
    Point(int X,int Y)
    {
        this->x = X;
        this->y = Y;
    }

    Point(int X,int Y,int Z)
    {
        this->x = X;
        this->y = Y;
        this->z = Z;
    }

    int getX()
    {
        return this->x;
    }

    int getY()
    {
        return this->y;
    }
    int getZ()
    {
        return this->z;
    }


    void setX(int xcs)
    {
        this->x = xcs; 
    }

    void setY(int igrec)
    {
        this->y = igrec;
    }

    void setZ(int zet)
    {
        this->z = zet;
    }

};


class AbstractGeometricFigure
{
    string Figuretype;
    bool is2D;
    int nbcorners;
    Point* Corners;
public:
    virtual int area() = 0;
    virtual int perimeter() = 0;

    void getCorners() {
        for (int i = 0; i < nbcorners; ++i) {
            cout << "(" << Corners[i].getX() << ", " << Corners[i].getY();
            if (is2D) {
                cout << ")\n";
            }
            else {
                cout << ", " << Corners[i].getZ() << ")\n";
            }
        }
    }

    void addCorner(int newcorner)
    {
        if (Corners!=NULL)
        {
            Point* varfuri = new Point[nbcorners];
        }
    }

};

But if you have the intention to explain to me what happens when I have a dynamic array o type class, class Point,and in that class I must not implement the default constructor. What should I do when I have an exercise like this at the exam? Update: but I am still waiting for someone to explain to me the answer to my questions.

I was also thinking about implementing it this way:

void addCorner(Point newcorner)
    {
        if (Corners!=NULL)
        {
                Corners[nbcorners] = newcorner;
        }
    }
Corina
  • 137
  • 1
  • 1
  • 12
  • 2
    Are you allowed to use `std::vector`? You should use it here. – super Jan 17 '20 at 12:40
  • no , I am not allowed, my teachers want me to hard code – Corina Jan 17 '20 at 12:43
  • Then I would suggest that you implement your own linked list (easier) or use placement new (harder). – super Jan 17 '20 at 12:44
  • 1
    I was not taught about linked list yet, I will learn about it next semester. – Corina Jan 17 '20 at 12:45
  • 2
    I highly doubt that you need to know how to add non-default-constructible classes to arrays then. It's not very straight forward. – super Jan 17 '20 at 12:47
  • probably, but this doesn't answer my questions – Corina Jan 17 '20 at 12:47
  • No, but my previous commment points you in the right direction. Placement new is what you need. – super Jan 17 '20 at 12:48
  • Does this answer your question? [Object array initialization without default constructor](https://stackoverflow.com/questions/4754763/object-array-initialization-without-default-constructor) – Alan Birtles Jan 17 '20 at 13:04
  • @Corina as side notes: 1. don't abuse of `this->` 2. do use `nullptr` instead of `NULL` even if your teacher said differently. 3. don't pass by copy class object (like point in your code) – Moia Jan 17 '20 at 13:06
  • 1
    you tell me to write code in a way but you didn't explain to me why would it be better that way. – Corina Jan 17 '20 at 13:41
  • @AlanBirtles NO – Corina Jan 17 '20 at 13:41

1 Answers1

2

If you really want varfuri to be an array containing the Point objects directly as elements, with all the semantics it has (e.g. pointer arithmetic etc.), and you are not allowed to use std::vector or similar library containers, then there is currently no completely legal way of doing this in C++.

You can theoretically allocate uninitialized memory blocks with operator new and use single-element placement-new's (via e.g. the various std::uninitialized_* standard library functions) to simulate the behavior of std::vector, but you are then technically not allowed to use a pointer to the first element as if it was a pointer to an array of elements, although in practice this would likely work out fine.

If you don't require array semantics, then you can just implement a linked list or similar non-contiguous container and use that. See comment below for a simpler alternative than a linked list.

Based on your given requirements, these seem to be the only solutions.


As noted by @interjay in a comment below this answer, instead of a linked list you might also just allocate an array of pointers initialized to nullptr:

auto varfuri = new Point*[nbcorners]{};

in which you consider nullptr a replacement of the default-constructed state and then you construct and add elements with new:

varfuri[i] = new Point(/*constructor arguments*/);

Make sure to delete every individual element and delete[] the array allocation when you are done.

This does however also have different semantics than an array of directly allocated elements would have. However it seems more reasonable as an assignment.

And none of these new uses would be considered ok in practice, because they are not going to behave correctly in the presence of exceptions. Instead one would at least wrap both allocations in std::unique_ptrs (if std::vector cannot be used for whatever reason).


Or (since C++17) you can allocate an array of std::optionals and consider the empty state of the std::optional as replacement for the default-constructed state. But I have the feeling that this isn't allowed by your instructor either.

walnut
  • 21,629
  • 4
  • 23
  • 59