C++ private class 动态n维数组

C++ private class dynamic n-dimensional array

我一直在 StackOverlow 上四处寻找答案,但我没有找到答案,所以我希望它不会与这里的任何 post 重复。

所以,我有下一个问题。
假设我有下 2 个 classes:Rectangle(它是从另一个 class 构建的,但目前与我们无关) 和 网格 。 他们跟随构造函数:

(矩形私有 topLeft 和 bottomRight 的点构造函数):

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

(矩形构造函数和 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)(假设我不想在 Grid 中初始化 Rectangle 的值,只是在内存中分配它们)

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

}

所以,正如你所理解的,我在 Grid 构造函数中遇到问题,出现以下错误
(错误 1 ​​错误 C2512:'Rectangle':没有合适的默认构造函数可用。)
但我只是不明白为什么它不起作用,有人建议我将 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];

所以我一直想念在 C++ 中处理 n 维数组的方法。

recs[index] = new Rectangle[index]; 尝试调用 Rectangle 的默认构造函数 index 次。如果你想一次创建多个对象,你可能想添加默认的 ctor 和简单的 setter 方法到你的 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;
};

然后,在创建循环中:

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,因为要创建二维数组,所以总的网格大小是高*宽。在创建索引长度的情况下,您将改为创建三角形网格(而且,第一个循环迭代将是 recs[0] = new Rectangle[0] - 一个零长度数组)。

如用户宏 A 所述,考虑使用 std::vector<Rectangle> 而不是原始指针(二维数组为 std::vector<std::vector<Rectangle>>

此外,请考虑更改您的设计,因为当前您正在创建矩形对象的网格 H x W,其中所有点(first/last 除外)都在相邻的矩形中重复(每个点都在左上角)一个矩形的右上角,另一个矩形的右上角,左下角...)。

我提出了一个 Grid class,它包含 2D 整数数组,并且有一个方法 Rectangle getRectangle(int x, int y) 可以 return 适当的 2 点集。 Modyfying 这样的 Grid class 会容易得多,而且您不必遍历所有 Rectangle,只需 ints

您可以使用 placement new:您最初预留足够的空间来存储对象数组,然后在各自的位置单独构造它们。

在您的代码中,它可能会变成(或多或少):

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::vectors 可以使您免于...

您收到错误 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 维数组,您已使用 RectanglePoint 类 将其明确限制为二维数组。如果数组是 n 维的,你的点也需要是 n 维的:

template<int dimensions>
class Point
{
    std::array<int, dimensions> coords;

    ...
};

class Point
{
    std::vector<int> coords;

    ...
};