9

I am using C++ to program a chess game. I want to create two class attributes for the class Board: ROWS and COLUMNS. In Java, I would declare they as static final and everything would work as I want. How I do the same declaration in C++? I need to access these attributes by "Board::ROWS" and "Board::COLUMNS" in other classes.

What I have is this, which is throwing compilation errors since ROWS and COLUMNS are not declared in the scope of the declaration of m_TileMap. Is there a good practice for doing this without using #define statement?

class Board {
  Tile *m_TileMap[ROWS][COLUMNS];

public:
  static const int ROWS = 8;
  static const int COLUMNS = 8;

  Board(int m[ROWS][COLUMNS]);
}
Lucas Kreutz
  • 369
  • 2
  • 4
  • 12

6 Answers6

5

declare your m_TileMap after the declaration of ROWS and COLUMNS

e.g.

class Board {

public:
  static const int ROWS = 8;
  static const int COLUMNS = 8;

  Board(int m[ROWS][COLUMNS]);

private:
  Tile *m_TileMap[ROWS][COLUMNS];
};

The reason for this is because in C++, the compiler does not read forward. So in order for ROWS and COLUMNS to be understood by the compiler when you declare m_TileMap, they need to be declared before.

Jimmy Lu
  • 4,810
  • 7
  • 25
  • 30
2

You can re-order the class members, so that ROWS and COLUMNS are declared before they're used:

class Board {
public:
  static const int ROWS = 8;
  static const int COLUMNS = 8;

  Board(int m[ROWS][COLUMNS]);

private: 
  Tile *m_TileMap[ROWS][COLUMNS];
};
Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
  • @LucasKreutz - You're welcome. And welcome to StackOverflow. You can upvote answers you find useful by clicking the up-triangle to their left. (This is available in addition to check-marking the answer most useful to you.) – Andy Thomas May 17 '13 at 18:20
1

Try use enums as following

class Board {
public:
    enum {ROWS = 8};
    enum {COLUMNS = 8};

private:
    Tile *m_TileMap[ROWS][COLUMNS];

public:
    Board(int m[ROWS][COLUMNS]);
};
Nikolay Viskov
  • 1,016
  • 6
  • 9
1

ROWS and COLUMNS have not yet been declared when the definition for m_TileMap is parsed. Simply move those definitions:

class Board {
  Tile *m_TileMap[ROWS][COLUMNS];

public:
  static const int ROWS = 8;
  static const int COLUMNS = 8;

  Board(int m[ROWS][COLUMNS]);
};

As an aside, if you don't need to ever take the address of ROWS or COLUMNS, an alternative would be to use an enum, like this:

class Board {
public:
  enum { ROWS = 8, COLUMNS = 8};
  Tile *m_TileMap[ROWS][COLUMNS];


  Board(int m[ROWS][COLUMNS]);
};

All this having been said, wouldn't life be so much simpler if you just used vector?

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • Thank you for the explanation. I'll use an enum, I think it's pretty better. I used an array cause I think it will be easier to use with a minimax algorithm. – Lucas Kreutz May 17 '13 at 18:16
0

You need to state the sizes in the class definition:

static const int ROWS = 8;
// etc.

And don't forget the ; after the class definition!

Cadoiz
  • 1,446
  • 21
  • 31
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
0

You could also use #define which is more C-style but also more performant than enums. The reason, why this is the fastest is that the compiler replaces every instance of eg ROW with the actual calue (8). Furthermore, the Java compiler also replaces static final-variables to the actual byte code (which can sometimes be a problem, see here)

In your example that would be:

#define ROWS 8;
#define COLUMNS 8;
class Board {
public:
  Board(int m[ROWS][COLUMNS]);
private:
  Tile *m_TileMap[ROWS][COLUMNS];
};

But be aware of the visibilities and the adress space - you shouldn't put definitions like the in the header, because you would then force them upon everybody.

For the header, this would be preferred: Let's say you have a header file (board.h) in which you specify

class Board {
public:
  static const int ROWS = 8;
  static const int COLUMNS = 8;
  //...
};

So everybody including your board.h can use Board::ROWS and Board::COLUMNS. (this is intended behavior) See this answer for reference.

Another difference worth mentioning is that these makros are untyped in comparison to const, which is typed (has type int for example while the defined value has none). Additionally, there are also dynamic constants, but that should be a bit too far off topic - further reading here. But also the defines in C/C++ can do much more, see here for example.

Another thing a bit prospective: the constant strings C++ equivalent of Java static final String (first answer)

Cadoiz
  • 1,446
  • 21
  • 31