【问题标题】:C++ 2D Arrays of an Object Constructor对象构造函数的 C++ 2D 数组
【发布时间】:2010-09-28 03:28:44
【问题描述】:

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

当我尝试编译时,我收到以下错误: 在构造函数 'Grid::Grid(int,int)' 中: 'squares' 不是一种类型 '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 文件中的构造函数不起作用,我不确定该怎么做。有人有解决办法吗?

【问题讨论】:

    标签: c++ class object multidimensional-array


    【解决方案1】:

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

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

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

    【讨论】:

    • 他不是按照他的问题。
    • 我误解了他的编译器信息。我认为他在其中的某个地方忘记了一个时期。
    【解决方案2】:

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

    例如:

    using namespace std;

    这些属于 cpp 文件。

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

    【讨论】:

      【解决方案3】:

      为避免出现大量内存问题,请使用向量组成的向量。

      在标题中

      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(...);
      

      如果你想要新的方块,或者使用智能指针向量的向量。

      【讨论】:

        【解决方案4】:

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

        int *squares;
        

        那么,下面一行会报错:

        squares = new squares[xPos][yPos];
        

        你真正需要的是二维数组的内存块:

        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++”实现类的方法。

        【讨论】:

          【解决方案5】:
          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. 添加如下成员函数:

          代码:

          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;。原因是所有间接或直接包含该文件的代码也将自动包含该行,因此可以看到 all of std::。只要代码尝试引用恰好由 C++ 标准库定义的名称,就会发生名称冲突。

          【讨论】:

            【解决方案6】:

            这不起作用:

            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.
            

            希望没有太多错别字。

            【讨论】:

              【解决方案7】:

              根据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 ) )
              {
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-02-20
                • 2016-04-05
                • 2015-03-12
                • 1970-01-01
                • 1970-01-01
                • 2013-07-09
                • 1970-01-01
                • 2013-10-20
                相关资源
                最近更新 更多