1

在我的 Dev C++ 中,我正在尝试创建一个 2D Array 类,它的作用类似于 Grid。但问题之一是我不确定对构造函数做了什么。

当我尝试编译时,出现以下错误: 在构造函数中 'Grid::Grid(int,int)': 'sqaures' 不是类型 'yPos' 不能出现在常量表达式中 [Build Error] [grid. o] 错误 1

这是头文件:

#ifndef GRID_H
#define GRID_H

using namespace std;

class Grid
{
      public:

      Grid(int xPos, int yPos);
      // Constructor
      // POST: Creates the squares of grid; (x,y) coordinates

      private:

      int squares;
      //2D Array
      //the squares; (x,y) coordinates of the grids      
};

#endif

这是grid.h功能的.cpp文件

#include <iostream>
#include "grid.h"

using namespace std;

Grid::Grid(int xPos, int yPos)
{
    squares = new squares[xPos][yPos];
    //Trying to make squares into a 2D array, and turn the values into the arguments
    //into the the x,y coordinates 
}

我在 .cpp 文件中的构造函数不起作用,我不确定该怎么做。有没有人有任何解决方案?

4

7 回答 7

4

与您的问题没有直接关系,但您不应该在头文件(.h/.hpp)文件中使用声明。

例如:

using namespace std;

这些属于 cpp 文件。

有关原因,请参阅Herb Sutters GOTW(本周大师)#53

于 2008-12-23T05:47:41.647 回答
4

您的代码存在一些问题。首先,您的成员变量“squares”应该是指向 int的指针,而不是int

int *squares;

然后,以下行将给出错误:

squares = new squares[xPos][yPos];

您真正需要的是 2D 数组的一块内存:

squares = new squares[xPos * yPos];

此外,您应该将此数组的维度保存在成员变量中(例如, "sizeX" 和 "sizeY" )

现在,您有一块内存,可以容纳一个二维正方形数组。我通常重载 () 运算符以访问此数组中的元素:

int &Grid::operator() (int x, int y)
{
      // you can check array boundaries here
      return squares[y + sizeX*x];
}

如果您对操作符有疑问,只需创建一个成员函数:

int Grid::get(int x, int y)
{
     // check array bounds
     return squares[y + sizeX*x];
}
void Grid::set(int x, int y, int value)
{
     // check array bounds
     squares[y + sizeX*x] = value;
}

最后,您需要一个析构函数来释放内存:

Grid::~Grid()
{
     delete [] squares;
}

这就是我喜欢的方式(“C-with-classes”风格)。在另一个答案中,David Norman 给出了一个很好的“标准 C++”实现你的类的方法。

于 2008-12-23T06:02:37.670 回答
2

为避免大量内存问题,请使用向量向量。

在标题中

class Grid
{
    ...
    std::vector< std::vector<squares> > squares;
    ...
}

在.cpp

Grid::Grid(int xPos, int yPos)
{
    squares.resize(xPos);
    for (int i = 0; i < xPos; i++) {
        squares[i].resize(yPos);
    }
}

稍后的:

squares[2][3] = square(...);

或者,如果您想新建正方形,请使用智能指针向量的向量。

于 2008-12-23T05:50:23.980 回答
1

你确定你的代码正确吗?您的正方形被定义为 int,而不是 int**?我不确定你是如何编译它的......

编辑:您从将正方形定义为 int 得到的错误消息。因此,它只能取一个整数。您的构造函数试图将整个数组分配给它。你对指针、数组、解引用和所有这些东西足够熟悉吗?二维数组通常很棘手。

如果你写好你的二维数组,你实际上可以使用一个数组,只需将二维地址映射到一个索引中。

于 2008-12-23T05:42:26.337 回答
1
Grid::Grid(int xPos, int yPos) {
    squares = new squares[xPos][yPos];
    //Trying to make squares into a 2D array, and turn the values into the arguments
    //into the the x,y coordinates 
}

那当然是错误的。你必须做new int[xPos][yPos]。运算符要求您给它一个类型。但是,你还没有完成。yPos必须在编译时知道。在你的例子中它不是。原因是它成为新表达式返回的类型的一部分:

int (*squares)[yPos] = new int[xPos][yPos];

由于类型是静态的,因此无法在运行时确定 yPos。你真正想要的是一个 int 的向量。但是我认为您想自己进行内存管理,因为您想学习语言规则。所以去吧:

  1. 制作正方形 a int*int *squares;
  2. 将构造函数中的行更改为squares = new int[xPos * yPos];
  3. delete[] squares;在你的析构函数中添加一行。
  4. 添加复制构造函数和复制赋值运算符,当您的实例被复制时,它们会沿着您的内存进行复制。
  5. 添加如下成员函数:

代码:

int & get(int x, int y) { return squares[y * yPos + x]; }

这将为您提供给定位置的整数。当然,您也可以重载operator[]以使用 2d 索引进行自然访问:

class Grid {
    struct proxy {
        proxy(int *row):row(row) { }
        int & operator[](int x) {
            return row[x];
        }
        int * row;
    };

    int * squares;
public:
    proxy operator[](int y) {
        return proxy(squares + yPos * y); 
    }
};

外部索引将选择行,内部将选择列。如果您必须正确管理内存,则可以更改为更好的解决方案。对于您的任务,boost::multi_array是理想的:Boost.MultiArray

其他问题

永远不要using namespace std;在头文件中做。原因是间接或直接包含该文件的所有代码也将自动包含该行,因此可以看到所有 std::。只要代码尝试引用恰好由 C++ 标准库定义的名称,就会发生名称冲突。

于 2008-12-23T06:07:40.343 回答
1

这不起作用:

squares = new squares[xPos][yPos];

你需要:

squares = new (int*)[xPos];
for (int x = 0; x < xPos; ++x) {
     squares[x] = new int[yPos];
}

就个人而言,这是错误的做法。我更喜欢

class Grid {

     class Row {
         int* row; // this is a pointer into Grid::grid
         int size; // this equals Grid::col_count and is only here for bounds checking
     public:
         Row(int s, int* r) : size(s), row(r) {}

         int& operator[](int col) {
             if (col >=0 && col < size) return row[col];
             throw OutOfBoundsException();
         }
     };

     int row_count, col_count;
     int* grid;
     Row* rows;

  public:
     Grid(int x, int y) : row_count(x), col_count(y) {
         rows = new (Row*)[row_count];
         grid = new int[row_count*col_count];
         int* grid_walk = grid;
         for (int i = 0; i < row_count; ++i) {
             rows[i] = new Row(col_count, grid_walk);
             grid_walk += col_count;
         }
     }
     ~Grid() { delete[] rows; delete[] grid; }

     Row& operator[](int row) {
         if (row ?= 0 && row < row_count) return rows[row];
         throw OutOfBoundsException();
     }

     int rows() const { return row_count; }
     int cols() const { return col_count; }

};

Grid checkers(8,8);

for (r = 0; r < checkers.row_count(); ++r) {
    for (c = 0; c < checkers.col_count(); ++c) {
        if ((r + c) % 2 == 1) checkers[r][c] = -1; // red space
        else if (r < 3) checkers[r][c] = 1; // player 1
        else if (r >= 5) checkers[r][c] = 2; // player 2
        else checkers[r][c] = 0; // open square
    }
}
// etc.

希望没有太多错别字。

于 2008-12-23T06:10:26.560 回答
1

根据大卫诺曼的回答,使用std::vector. 但是他的回答中有一个错误,向量应该声明如下:

class Grid
{
...

    std::vector< std::vector<int> > squares;
};

您还可以使用带有大小和值的向量构造函数对其进行初始化:

Grid::Grid(int xPos, int yPos)
:   squares( xPos, std::vector<int>( yPos, 0 ) )
{
}
于 2008-12-23T11:06:43.937 回答