对象构造函数的C ++ 2D数组

时间:2008-12-23 05:39:29

标签: c++ class object multidimensional-array

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

当我尝试编译时,我收到以下错误: 在构造函数'Grid :: Grid(int,int)'中: 'sqaures'不是一种类型 'yPos'不能出现在常量表达式中 [构建错误] [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文件中的构造函数不起作用,我不确定该怎么做。有没有人有任何解决方案?

7 个答案:

答案 0 :(得分:4)

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

int *squares;

然后,以下行会出错:

squares = new squares[xPos][yPos];

你真正需要的是2D阵列的内存块:

squares = new squares[xPos * yPos];

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

现在,你有一块内存,它将容纳一个2D正方形阵列。我经常重载()运算符以访问此数组中的元素:

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 ++”方式来实现你的课程。

答案 1 :(得分:3)

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

例如:

using namespace std;

这些属于cpp文件。

请参阅Herb Sutters GOTW (Guru of the Week) #53了解原因。

答案 2 :(得分: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(...);

如果你想要新的正方形,可以使用智能指针矢量向量。

答案 3 :(得分:1)

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

编辑: 您获得的错误消息是您将方块定义为int的结果。因此,它只能取一个整数。您的构造函数正在尝试将整个数组分配给它。你是否熟悉指针,数组,解除引用和所有这些东西?二维阵列通常很棘手。

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

答案 4 :(得分: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. 将方块设为int*int *squares;
  2. 将构造函数中的行更改为squares = new int[xPos * yPos];
  3. 在析构函数中添加delete[] squares;之类的行。
  4. 添加复制构造函数和复制分配运算符,以便在复制实例时复制内存。
  5. 添加如下所示的成员函数:
  6. 代码:

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

    这将给出给定位置的整数。当然,您也可以使用2d索引重载operator[]以获得自然访问权限:

    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 ++标准库定义的名称,就会发生名称冲突。

答案 5 :(得分: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.

希望没有太多错别字。

答案 6 :(得分:1)

根据David Norman's answer,使用std::vector。但是他的答案中有一个错误,矢量应该声明如下:

class Grid
{
...

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

您也可以使用带有大小和值的矢量构造函数初始化它:

Grid::Grid(int xPos, int yPos)
:   squares( xPos, std::vector<int>( yPos, 0 ) )
{
}