在我的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文件中的构造函数不起作用,我不确定该怎么做。有没有人有任何解决方案?
答案 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文件。
答案 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的向量。但我想你想自己做内存管理,因为你想学习语言规则。所以请坚持下去:
int*
:int *squares;
squares = new int[xPos * yPos];
delete[] squares;
之类的行。 代码:
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 ) )
{
}