1

私の Dev C++ では、Grid のように機能する 2D Array クラスを作成しようとしています。しかし、問題の 1 つは、コンストラクターが何をするかわからないことです。

コンパイルしようとすると、次のエラーが発生します: In constructor 'Grid::Grid(int,int)': 'sqaures' is not a type 'yPos' cannot appear in a constant-expression [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 (Guru of the Week) #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" )。

これで、正方形の 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++」の方法を提供しています。

于 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

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 ) )
{
}
于 2008-12-23T11:06:43.937 に答える
1

コードを正しく理解していますか? あなたの正方形は int** ではなく int として定義されていますか? これをどのようにコンパイルするのかわかりません....

編集: 正方形を int として定義すると、エラー メッセージが表示されます。したがって、単一の整数のみを取ることができます。コンストラクターは、配列全体をそれに割り当てようとしています。ポインター、配列、逆参照などについて十分に理解していますか? 一般に、2 次元配列は扱いにくいものです。

2D 配列を適切に記述すれば、実際には 1 つの配列を使用して、2 次元のアドレスを 1 つのインデックスにマップするだけで済みます。

于 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. 正方形を にし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 に答える