omerfarukdogan
omerfarukdogan

Reputation: 869

Why does #ifndef not work in this situation?

Note: The question has already been answered here undirectly

The problem is not include guards : they won't help across different translation units


Note: I know the solution is to use extern keyword.

I'm new to C++. I have a problem understanding #ifndef in header files. When I do something like this, I get an error saying that the variables game_over and turn are already defined.

/*chess.h*/
#ifndef CHESS
#define CHESS
#include <iostream>
#include "chessboard.h"
using namespace std;

bool game_over;
char turn;
chessboard board;

int main();
#endif

/*bishop.cpp*/
#include "bishop.h"
#include "chess.h"
bishop::bishop(string pos, char color)
{
    int x = pos[0] - 97;
    int y = pos[1] - 1;
    name = "bishop";
    this->color = color;
    board.add_new(*this);
}

/*chess.cpp*/
#include "chess.h"

int main()
{
    ...
}

Why are the variables defined twice in here? I thought that first time when chess.h is included, CHESS is defined. So in bishop.cpp, #include "chess.h" will not do anything since the header will skip to #endif from #ifndef CHESS. But it does not work like that obviously. Why am I wrong?

Upvotes: 0

Views: 2297

Answers (1)

Mark Ransom
Mark Ransom

Reputation: 308138

The #ifndef only blocks the code if the symbol is defined within the same translation unit, at a point before the #ifndef. A translation unit is a source file (.cpp) and all the files that are included into it. Since you're compiling two source files, they'll both have a complete include of the .h file.

You already appear to know how to handle the problem of defining global variables in a header file: declare them extern in the header, and put a definition into one of the sources. I would be remiss though if I didn't warn you to avoid globals in the first place, as your programs grow they'll make your life difficult.

Upvotes: 2

Related Questions