0

I am trying to compile this code:

class OthelloState {
public: // constructor 

    Othello(int r, int c);

/* other stuff */

private: // private data

    const int rows;

    const int columns;

    int board[rows][columns];
}

I keep ending up with:

OthelloState.h:109: error: invalid use of non-static data member 'OthelloState::rows'
OthelloState.h:115: error: from this location
OthelloState.h:115: error: array bound is not an integer constant
OthelloState.h:112: error: invalid use of non-static data member 'OthelloState::columns'
OthelloState.h:115: error: from this location
OthelloState.h:115: error: array bound is not an integer constant

I assume that this means I have to make rows and columns static. But if I make them static, I cannot initialize either with from a constructor, the way I have to for this project...

Is there some other way I can do this?

PS: I know that in real Othello, the board is a square 8 by 8 grid...But after considering how long it would take the computer to generate the next best move on a partial 8 by 8 grid, we are not going to play with "real" Othello board (i.e. no predefined board sizes).

Matthew Denaburg
  • 163
  • 1
  • 15

4 Answers4

3

In C++, variable length arrays are not allowed. board[][] needs to know both of its dimensions at compile time. You can use vector<vector<int> > board;, if you want to initialize row and col at runtime.

class OthelloState {
public:
    OthelloState(int r, int c);

private: // private data
    const int rows;  // should be 'unsigned int'
    const int columns;

    vector<vector<int> > board;  
};

Other solution:

Suppose you know rows and cols at compile time then you can use template. That is as good as initializing row and col in constructor.

template<unsigned int row, unsigned int col>
class OthelloState {
public:
...
private:
  int board[row][col];
};

Usage:

  OthelloState<8,8> obj;
  OthelloState<10,10> obj;
iammilind
  • 68,093
  • 33
  • 169
  • 336
0

You're trying to dynamically define the size of a compile-time, fixed size array at runtime. You will need to dynamically allocate the memory. You also need your constructor to have the same name as your class

class OthelloState {
public: // constructor 

OthelloState(int r, int c)
{ 
   board = new int[r];
   for(int i = 0; i < r; i++)
   {
      board[i] = new int[c];
   }
}


/* other stuff */

private: // private data

   const int rows;

   const int columns;

   int **board;
};

Make sure you have matching deletes for all your news in a destructor if you use this method, though

Joshua Clark
  • 1,346
  • 3
  • 14
  • 24
  • 1
    I do not recommend this approach. You're just asking for dangling pointer problems. You need to provide a copy constructor and copy assignment so that deep copies are made (or alternatively, make the copy-ctor and assignment private to make the class non-copyable). – Emile Cormier Nov 02 '11 at 03:50
  • `vector< vector >` does exactly the same thing as this solution without all the memory management pitfalls. – Emile Cormier Nov 02 '11 at 03:51
  • Yes, proper memory management in required, but it's a solution for creating a _primitive_ 2-d array when the size is not known until runtime. I agree that `vector< vector >` is at least a safer way to create _some_ 2-dimensional matrix, but I don't think it's the best answer to the question as it's stated. – Joshua Clark Nov 02 '11 at 04:04
  • shouldn't it be board[*i*] = new int[c]; ? – jakev Aug 29 '12 at 21:19
0

if it's always 8x8, then constants are a minimal solution. here's one way to declare it:

class OthelloState {
    // ...
private:
    enum { rows = 8, columns = 8 };
    int board[rows][columns];
};
justin
  • 104,054
  • 14
  • 179
  • 226
0

But after considering how long it would take the computer to generate the next best move on a partial 8 by 8 grid, we are not going to play with "real" Othello board (i.e. no predefined board sizes).

I deduce from that sentence that you're working on a homework assignment. If that's the case, then it might not be possible/practical for you to use Boost.MultiArray (unless your instructor advised you that it's okay to use Boost).

That leaves vector< vector<int> > which are a PITA to initialize properly. Before you can even use vector< vector<int> >, you have to loop through each inner vector and resize it.

Boost.MultiArray is basically just an overglorified wrapper around a 1D array of data. I therefore propose a third alternative: Roll up your own 2D wrapper around a flat one-dimensional vector. You can overload operator() to mimic the [][] behavior of 2D arrays:

int operator()(size_t row, size_t col) {/*compute index into 1D array*/}

I posted an example of this kind of wrapper here.

Community
  • 1
  • 1
Emile Cormier
  • 28,391
  • 15
  • 94
  • 122