Itay.V Itay.V - 12 days ago 8
C++ Question

C++ private class dynamic n-dimensional array

i've been looking all around StackOverlow for an answer but i didnt find one so i hope it isnt duplication of any post around here.

so, i have the next problem.

lets say i have the next 2 classes: Rectangle (Which is built from another class but it doesnt concern us currently)
and Grid.
with they following constructors:

(Point Constructor for Rectangle private topLeft and bottomRight):

Point::Point(int x, int y) {this->x = x; this->y = y;}


(Rectangle Constructor and Class)

class Rectangle
{
public:
Rectangle(int l, int u, int w, int h, int color);
//int getColor() const;
//void setColor(int color);
//bool contains(const Point &p) const;
//void print() const;
private:
const Point topLeft, bottomRight;
int color;
};

Rectangle::Rectangle(int l, int u, int w, int h, int color) :
topLeft(l, u),
bottomRight(l + w, u + h)
{ this->color = color; }


(Grid Constructor and Class) (Lets assumt i dont want to intialize the valuse of Rectangle in Grid just allocate them in memory)

class Grid
{
public:
Grid(int tileW, int tileH, int width, int height, int color);
//~Grid();
//Rectangle& getRectAt(const Point &p);
//void print() const;
private:
int count;
Rectangle **recs;
};

Grid::Grid(int tileW, int tileH, int width, int height, int color)
{
int index, index_c=0;
recs = new Rectangle *[width];

for (int index = 0; index < width; index++)
{
recs[index] = new Rectangle[index];
}

}


so, as you can udnerstand i have problem in Grid constructor with the following Error

(Error 1 error C2512: 'Rectangle' : no appropriate default constructor available.)

but i just cant understand why it wont work, i've been suggested to allocate the Recs double pointer as 1 dimensional array (Array with the length of Width*Height) but what if Recs was 4 dimensional array ? How could you flat it properly and then index around the 4-dimensional array without having a headache calculating the index of each cell in the array.

another thing, we know that if it was int** and not recs** it would work perfectly

int **foo;
int height,width;
foo = new int* (height);
for (int index = 0; index<height; ++index)
foo[index] = new int[width];


so i just keep missing the way of doing n-dimensional arrays in C++.

Answer

The line recs[index] = new Rectangle[index]; tries to call Rectangle's default constructor index times. If you want to create multiple objects at once, you probably want to add default ctor and simple setter method to your Rectangle class

class Rectangle
{
public:
    Rectangle(int l, int u, int w, int h, int color);
    Rectangle() = default;
    void set(int l, int u, int w, int h, int color);
private:
    const Point topLeft, bottomRight;
    int color;
};

Then, in creation loop:

for (int index_w = 0; index_w < width; index_w++)
{
    recs[index_w] = new Rectangle[height]; //see note below
    for (int index_h = 0; index_h < height; index_h++)
        recs[index_w][index_h].set(/* some math with width, height and loop variables*/, color);
}

Note: I have changed index to height, because you want to create 2D array, so the total grid size is height * width. With index length in creation, you would create triangle-shaped grid instead (and more over, the first loop iteration would be recs[0] = new Rectangle[0] - a zero-length array).

As user Macro A mentioned, consider using std::vector<Rectangle> instead of raw pointers (2D array would be std::vector<std::vector<Rectangle>>)

Also, consider changing your design, because currently you are creating a grid H x W of Rectangle objects, where all points (except first/last) are duplicated across adjacent rectangles (each point is upper-left corner of one rectangle, upper-right corner of another, bottom-left...).

I propose a Grid class that holds 2D array of ints and has a method Rectangle getRectangle(int x, int y) which would return appropriate set of 2 points. Modyfying such Grid class would be much easier, and you wouldn't have to iterate over all Rectangles, just ints