Я искал ответ вокруг StackOverlow, но я не нашел такого, поэтому я надеюсь, что это не дублирование какого-либо сообщения здесь.
Итак, у меня есть следующая проблема.
допустим, у меня есть следующие 2 класса: Прямоугольник (Который построен из другого класса, но в настоящее время нас это не касается)
а также сетка.
со следующими конструкторами:
(Конструктор точек для частных прямоугольников topLeft и bottomRight):
Point::Point(int x, int y) {this->x = x; this->y = y;}
(Конструктор и класс прямоугольника)
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) (допустим, я не хочу инициализировать значения Rectangle в Grid, просто выделю их в памяти)
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];
}
}
Итак, как вы можете понять, у меня есть проблема в конструкторе сетки со следующей ошибкой
(Ошибка 1, ошибка C2512: «Прямоугольник»: нет подходящего конструктора по умолчанию.)
но я просто не могу понять, почему это не сработает, мне предложили выделить двойной указатель Recs как одномерный массив (массив с длиной Width * Height), но что если Recs был 4-мерным массивом? Как вы могли бы выровнять его правильно, а затем индексировать вокруг 4-мерного массива, не испытывая головной боли при расчете индекса каждой ячейки в массиве.
другое дело, мы знаем, что если бы это было int **, а не recs **, это работало бы отлично
int **foo;
int height,width;
foo = new int* (height);
for (int index = 0; index<height; ++index)
foo[index] = new int[width];
поэтому я просто упускаю способ создания n-мерных массивов в C ++.
Линия recs[index] = new Rectangle[index];
пытается вызвать конструктор Rectangle по умолчанию index
раз. Если вы хотите создать несколько объектов одновременно, вы, вероятно, захотите добавить ctor по умолчанию и простой метод установки в ваш класс Rectangle.
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;
};
Затем в цикле создания:
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);
}
Заметка: Я изменился index
в height
потому что вы хотите создать 2D массив, поэтому общий размер сетки будет высота * ширина. При создании длины индекса вместо этого вы бы создали треугольную сетку (и более того, первая итерация цикла будет recs[0] = new Rectangle[0]
— массив нулевой длины).
Как упомянул пользователь Macro A, рассмотрите возможность использования std::vector<Rectangle>
вместо необработанных указателей (2D-массив будет std::vector<std::vector<Rectangle>>
)
Кроме того, рассмотрите возможность изменения вашего дизайна, потому что в настоящее время вы создаете сетку H x W объектов Rectangle, где все точки (кроме первой / последней) дублируются на смежных прямоугольниках (каждая точка — это верхний левый угол одного прямоугольника, верхний правый угол другой, левый нижний …).
Я предлагаю класс Grid, который содержит двумерный массив целых и имеет метод Rectangle getRectangle(int x, int y)
который вернул бы соответствующий набор из 2 баллов. Модификация такого класса Grid будет намного проще, и вам не придется перебирать все прямоугольники, только целые
Вы могли бы использовать размещение нового : вы изначально резервируете достаточно места для хранения массива объектов, а затем индивидуально создаете их каждый на своем месте.
В вашем коде это может стать (более или менее):
for (int index = 0; index < width; index++)
{
// first simple allocation for the array
recs[index] = (Rectangle *) malloc(sizeof(Rectangle) * height);
for (int j=0; j<height; j++) {
// individually build each rectangle in place
new(&recs[index][j]) Rectangle(index*tileW, j*tileH, tileW, tileH, color);
}
}
Это предназначено для того, чтобы делать именно то, что вам нужно: создавать массивы конструируемых объектов по умолчанию.
Несвязанный: поскольку вы используете сырые указатели и выделенные массивы, не забудьте правильно все освободить. С помощью std::vector
может спасти тебя от этого …
Вы получаете ошибку C2512, потому что у вас нет конструктора по умолчанию в Rectangle
, Единственный конструктор, который у вас есть Rectangle
параметризован, в то время как конструктор по умолчанию требует, чтобы он вызывался без дополнительных аргументов.
Глядя на линию recs[index] = new Rectangle[index];
вы видите, что нет никаких аргументов для 5 параметров, которые принимает конструктор. Для компиляции этой строки вам нужно создать конструктор по умолчанию либо с новым конструктором с подписью Rectangle()
или аргументы по умолчанию для параметров в вашем параметризованном конструкторе, например Rectangle(int l = 0, int u = 0, int w = 0, int h = 0, int color = 0);
,
Если вы хотите выделить память, вы должны создать конструктор по умолчанию и использовать std::vector<Rectangle>
который вы инициализируете с размером. Затем вы можете позже заменить объекты с помощью конструктора копирования, как показано в этом примере: http://ideone.com/KnUBPQ
Что касается создания n-мерного массива, вы явно ограничили его двумерным массивом с помощью Rectangle
а также Point
классы. Если массив будет n-мерным, ваши точки тоже должны быть n-мерными:
template<int dimensions>
class Point
{
std::array<int, dimensions> coords;
...
};
или же
class Point
{
std::vector<int> coords;
...
};