views:

221

answers:

5

Hello!

Yet another Scrabble project question... This is a simple one.

It seems I am having trouble getting my global constants recognized:

My board.h: http://pastebin.com/7a5Uyvb8

Errors returned:

1>C:\Users\Francisco\Documents\FEUP\1A2S\PROG\projecto3\projecto3\Board.h(34): error:     variable "TOTAL_ROWS" is not a type name
1>      vector< vector<Cell> > _matrix(TOTAL_ROWS , vector<Cell>(TOTAL_COLUMNS));
1>
1>main.cpp
1>compilation aborted for .\Game.cpp (code 2)
1>Board.cpp
1>.\Board.h(34): error: variable "TOTAL_ROWS" is not a type name
1>      vector< vector<Cell> > _matrix(TOTAL_ROWS , vector<Cell>(TOTAL_COLUMNS));
1>                                     ^
1>

Why does this happen? Why is the compiler expecting types?

Thanks for your time!

EDIT:

Disregard my previous edit... This is my default constructor: Board::Board() { _matrix(TOTAL_ROWS, vector(TOTAL_COLUMNS)); }

I get the following error.

1>.\Board.cpp(16): error: call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type
1>       _matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS));
1>       ^

Why does this happen?


I managed to solve all the problems with my file. I used

Board::Board() :
     _matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS))
     {}

instead. Thanks for all your help!

A: 

You can't call a constructor in the header file (or any code for that matter).

robarson
I'm sorry, I did not understand.
Francisco P.
While I understand what you are trying to say, your answer like it is formulated now is wrong in so many ways...
KillianDS
+1  A: 

In your header file, I see:

private:
    vector< vector<Cell> > _matrix(TOTAL_ROWS , vector<Cell>(TOTAL_COLUMNS));

This seems to be declaring a private member variable, _matrix, and is apparently an effort to call the constructor for _matrix at the same time. You cannot call the constructor in this way.

Remember that your header file may be included in MANY program files. As a result, headers should not contain execution instructions (certain exceptions exist, such as inline methods and templates). You never know where the header will be included, so you never know where the code in a headerfile will appear.

It is good advice to write your header files so that they are safe to be included anywhere.

If you want to continue this code, I suggest: The constructor of Board() should construct the member variable explicitly:

Board::Board() :
    _matrix(TOTAL_ROWS, .....);
    // This will call the matrix constructor ONLY when the Board constructor is called.
{
}

Then the Board constructor should be called, but ONLY in a .cpp file, not in a .h file.

abelenky
In fact headers *must* contain the definitions of inline and template methods.
Mark B
That is not what I meant to do. I meant to make `_matrix` a vector of vectors with TOTAL_COLUMNS * TOTAL_ROWS dimension. What is the correct way to do this?
Francisco P.
@Mark B: don't confuse the beginner by introducing inline stuff. Beginners need to know that header files should not include processing instructions (except when they really, really need to).
abelenky
I would recommend against confusing beginners by lying to them, personally. You make a lot of extremely strong statements.
Dennis Zickefoose
Strong statements revised.
abelenky
+2  A: 

You try to initialize the vector on it's definition, which is not the correct way to do this for object variables, the correct way is this:

extern const unsigned int TOTAL_ROWS = 15;
extern const unsigned int TOTAL_COLUMNS = 15;
class Board
{
public:
        Board() : _matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS)) {}
private:
        vector< vector<Cell> > _matrix;
};
KillianDS
+4  A: 

The way that is written, you are defining a function called _matrix that returns a vector. So TOTAL_ROWS is expected to be a type name, since it is being parsed as a paramter type. I assume what you are trying to do is define a variable called _matrix that is a vector.

What you want to do is leave off the constructor, and initialize the variable inside your constructor. Only constant integral values can be initialized in the body of the class, at least in the current version of the standard.

Leaving off the unimportant parts:

  Board() : _matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS)) { }

private:
  vector< vector<Cell> > _matrix;

Note that this is just an example. Presumably you have an implementation file with an actual body for Board(), and you should put the initialization there rather than directly in the header or you'll get errors. The important thing is that you should not do it when you declare _matrix initially.


For your new question, extern const unsigned int TOTAL_COLUMNS = 15; defines TOTAL_COLUMNS every time Board.h is included by a file. Constant variables at namespace scope have internal linkage by default, so if you leave off the extern you will be okay.

In general, if the variable isn't constant, you take an approach similar to the one for _matrix. You leave off the initialization in the header, and then inside an implemenation file put it back on:

board.h: extern const int TOTAL_COLUMNS;

board.cpp: extern const int TOTAL_COLUMNS = 15;

Dennis Zickefoose
+1  A: 

This is my default constructor:

Board::Board() { _matrix(TOTAL_ROWS, vector(TOTAL_COLUMNS)); }

I get the following error. [ .... ]

You did not follow the examples and syntax provided by @Dennis Zickefoose, @KillianDS, and myself.

Please re-read our answers and study our code.

abelenky
You are correct. Sorry.
Francisco P.