Why does #ifndef not work in this situation? - c++

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?

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.

Related

Global Constants in .h included in multiple c++ project

I want to run a small simulation in c++.
To keep everything nice and readable I seperate each thing (like all the sdl stuff, all the main sim stuff, ...) into it's own .h file.
I have some variables that I want all files to know, but when I #include them in more then one file other the g++ compliler sees it as a redefinition.
I understand why he does this, but this still leaves me with my wish to have one file where all important variables and constants for each run are defined and known to all other files, to easily find and change them when running my simulation.
So my Question here: Is there a good workaround to achieve that or something similar?
You can put the declarations for all the globals in a header and then define them in a source file and then you will be able to use those global variables in any other source file by just including the header as shown below:
header.h
#ifndef MYHEADER_H
#define MYHEADER_H
//declaration for all the global variables
extern int i;
extern double p;
#endif
source.cpp
#include "header.h"
//definitions for all the globals declared inside header.h
int i = 0;
double p = 34;
main.cpp
#include <iostream>
#include "header.h" //include the header to use globals
int main()
{
std::cout << i <<std::endl;//prints 0
std::cout<< p << std::endl;//prints 34
return 0;
}
Working demo
Mark them as extern in the header and have one translation unit that defines them.
Note: Without LTO (link time optimization) this will seriously slow down your simulation.

If you include something in the .h file Do you have to include the same thing again?

So I am just wondering if you #include something in a for example header.h file:
For example this is called header.h:
#include <vector>
#include <iostream>
#include <somethingElse>
So if for example I make a file called something.cpp Do I need to put all those include statements again?
#include "header.h"
// If I include #header.h in this file. Do the #include carry over to this file. Or do they not
I am wondering because whenever I include <vector> something in my .h file the #include statements that I used previously in the .h file always turn grey which means they are not used. Is it because I used it in the .h file? Its not a problem or anything I am just curious.
You don't need to include those headers again because your compiler can find those headers. You can also try to read and understand the makefile (or CMakeList) which will help.
Try always to avoid "Multiple file inclusion" via using inclusion guard or #pragma once in order to prevent the multiple file inclusion.
To include file means that the content of the file will be added to the very place you wrote include.
Here's an example:
// header.h
const int vlaue = 10;
const int value2 = 0;
// main.cpp
#include "header.h"
#include "header.h"
Above the content of "header.h" is added twice to main.cpp.
Do you know what is the result? It's a compile-time error complaining of redefinition of value and value2.
In the above example I think green programmers don't get trapped by it but it is just an explanation, So what I talk about is when a huge program where many header files and many source files and some files include others then it'll be so difficult to track the right file inclusion.
The workaround that is to use inclusion guards or pragma once eg:
Let's modify our header.h to look like:
// header.h
#ifndef MY_HEADER_H
#define MY_HEADER_H
const int vlaue = 10;
const int value2 = 0;
#endif
Now in main.cpp:
#include "header.h"
#include "header.h"
#include "header.h"
The code above works fine and no duplicate of header content is added to main.cpp. Do you know why? It's the magic of Macro there. So at first time the pre-processor checks whether a macro has been already defined with the name MY_HEADER_H or not and for sure for the first time it is not defined so the content is added. The second and so on the condition fails because the macro is already defined thus the content of header.h will not be added to where it is called.
The draw back of inclusion guard is if you have a macro with same name as the inclusion guard thus it is already defined so the content will never be added (empty content). Thus you get a compile-time error:
value, `value2` undeclared identifiers.
The second solution is using pragma eg:
Let's modify our header.h file:
// header.h
#pragma once
const int vlaue = 10;
const int value2 = 0;
// main.cpp
#include "header.h"
#include "header.h"
The code above works correctly so no multiple inclusion of header.h That is because of the magic of pragma once: which is a non-standard but widely supported pre-processor directive designed to cause the current source file to be included only once in a single compilation. Thus, #pragma once serves the same purpose as include guards, but with several advantages, including: less code, avoidance of name clashes, and sometimes improvement in compilation speed.
Finally you should include header wherever their content is used eg:
// Shape.h
class Shape{
// some code here
};
// Cube.h
#include "Shape.h"
class Cube : public Shape{
// some code here
};
// Cuboid.h
// #include "Shape.h"
#include "Cube.h" // So here the Shape.h is added to Cube.h and Cube.h is added here.
class Cuboid : public Cube{
// some code here
};
As you can see above the content of Shape.h is added to Cuboid.h indirectly because it is added to Cube.h and cuboid.h includes Cube.h so it is added to it. So without inclusion guards or pragma once if you include the two headers in one source file you get duplicate content there.

How to Include-guard when using multiple headers on a main.cpp?

I'm learning C++ in a course, using Visual Studio 2013, and I have an issue with include-guards on my main.cpp. I can't use either class or #pragma once (though they work) due to conditions my professor said.
If I only use Coordinates and Line, and I use in main.cpp the #include Line.h (which get code from both Line and Coordinates), this works ok, but when I add Rectangle and Triangle (both have #include "Line.h"), then it throws the "already defined" error LNK2005 several times.
Is there something missing?
This is my code:
Coordinates.h
#ifndef Coordinates
#define Coordinates
//Code declaration. Other headers have similar declaration
struct CoordinatesType { double x, y; } coordinates;
void setCoordinates(double x, double y);
CoordinatesType getCoordinates();
#endif
Coordinates.cpp
#include "Coordinates.h"
//Code implementation
Line.h
#ifndef Line
#define Line
#include "Coordinates.h"
//Code declaration
#endif
Line.cpp
#include "Line.h"
#include <math.h>
//Code implementation
Rectangle.h
#ifndef Rectangle
#define Rectangle
#include "Line.h"
//Code declaration
#endif
Rectangle.cpp
#include "Rectangle.h"
//Code implementation
Triangle.h
#ifndef Triangle
#define Triangle
#include "Line.h"
//Code declaration
#endif
main.cpp
#include "Triangle.h"
#include "Rectangle.h"
int main(){
//Do stuff here.
}
If you need me to add the implementation and declaration codes, let me know, but I feel like it has to do with the include-guard.
EDIT: I'll add code in the Coordinate header so you can get an idea of what I'm doing and to avoid consuming a lot of space in the post. Remember, I can't use class Coordinates{} due to my professor's restriction to not use it.
This error is a linker error, not a compiler error.
Header guards do nothing for the linker.
You have successfully guarded against multiple declarations of things within the same translation unit, but you have not guarded against multiple definitions of things across your whole program.
The way to guard against that is to, well, not do that. There should be no non-inline, non-template definitions of anything in your header if you want to include it into multiple source files.
Here, you declare a type CoordinatesType, and create an object of that type:
struct CoordinatesType { double x, y; } coordinates;
Don't do that! Create an instance of CoordinatesType only in a source file, not in a header. Otherwise, every source file that includes this header (directly or indirectly) will get its own coordinates object and your linker complains about the name collision.
The code should be:
struct CoordinatesType { double x, y; };
Then, either coordinates in the one source file in which you wish to use the object… or extern on its declaration in a header. There are better approaches but I shan't enumerate them all here since this topic has been covered to death on SO already. Furthermore, your C++ book will have an explanation.
But the long and short of it is that this has nothing to do with header guards.
As already pointed out, your problem has nothing to do with include-guards.
Your problem is in this line:
struct CoordinatesType { double x, y; } coordinates;
While the declaration of the struct
struct CoordinatesType { double x, y; };
may appear in multiple .cpp files, as long as it is identical (it is, since you include the same header-file), you also define a variable
CoordinatesType coordinates;
in the same line. Since a definition is only allowed once, your linker complains.
If you really need a global variable of that type (check if you really need one, as it might not be necessary), change your header to a declaration:
struct CoordinatesType { double x, y; };
extern CoordinatesType coordinates;
and use a definition
CoordinatesType coordinates;
in exactly one cpp-file.
Note that the error didn't happen when only including Line and Coordinates, because your include-guards work and you only include the headers in a single .cpp file
Coordinates.h doesn't have any include guard.
When you include it multiple times, it defines Coordinates only once, but the rest of the file is included multiple times.
Put the #endif in the right place.
PS. The identifiers used in the include guards should be something that is never, ever used elsewhere by coincidence. I wouldn't be surprised if someone tried to use a variable named Line or Triangle. And since you #define those, that will lead to very unexpected errors. Use something like #define LineHeader_Included__ .

Redefinition Error after moving code into another Header

so i'm having a problem: I cutted out some coding(structs) and pasted it in a new Header-file. I included the new Header-file everywhere it is needed, so it shouldnt get me an error, but after i tried building my dll file, i got tons of errors saying that those structs i cutted out/pasted are redefinitions. I clicked on some of those "redefinitions" and the "originals" and i got to the same struct the same time, meaning there is only one of them so it cant be a redefinition. I'm so confused at the moment and i would really appreciate some help! Thanks in advance :)
EDIT:
i moved this:
struct Game_s
{
bool loaded;
bool FirstUser;
bool AlwaysVerfied;
bool DoingUnlockAll;
int Globaltimer;
int MaxUnlockAll;
time_t t;
};
Game_s Game;
from a Header file called MW2Class.h to another class called Structs.h, looking like this:
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <xbox.h>
struct Game_s
{
bool loaded;
bool FirstUser;
bool AlwaysVerfied;
bool DoingUnlockAll;
int Globaltimer;
int MaxUnlockAll;
time_t t;
};
Game_s Game;
Your issue is you have a global variable declared in your header file
Game_s Game;
Is going to add Game to every translation unit you include the header in(include guards do not stop this). When you get to the linking stage the linker will see all of theses global variables that are the same and will not know what to do with them.
If you really want the global variable you will need to declare it with extern and define it in one translation unit. For more information on that see: Global variables in header file
Make sure to add the inclusion guard to your headers :
Suppose your header is test_file.hpp, the include guards will be :
#ifndef TESTFILE_HPP_
#define TESTFILE_HPP_
#endif
That prevents multiple inclusions of your header.
Edit :
1 - in your case
#ifndef STRUCTS_H_
#define STRUCTS_H_
#endif

Why am I getting linking errors even with header guards? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does this not prevent multiple function declarations?
Global.h
#ifndef Global_h
#define Global_h
#include <iostream>
unsigned char exitStatus;
#endif
OutputHandler.h
#ifndef OutputHandler_h
#define OutputHandler_h
#include "Global.h"
class OutputHandler {
private:
static bool instanceExists;
// more code
#endif
Root.h
#ifndef Root_h
#define Root_h
// declarations
OutputHandler *output;
#endif
Root.cpp
#include "Root.h"
// gets instance of OutputHandler
// more code
I am getting errors regarding exitStatus, static bool instanceExists, and static class output being already defined by Root.obj in OutputHandler.obj. I assume the issue is with including the header file OutputHandler.h in both Root.h and OutputHandler.cpp. Anyone know how to fix this or how to better organize header files?
Because include guards only work at the translation unit level (you can, for this simple case, consider a single C file to be a translation unit).
That means a single C file, if it includes the header file twice, will not process it the second time due to the include guards.
However, if you include the header from two different C files, each of them will get a copy of the variables defined in that header.
Then, when you link them together, you get the duplicates.
The easiest way to get around this problem is to never define things in headers, only declare them.
So, in the header (eg, xyzzy.h), you have:
extern int xyzzy; // declare but don't define.
and in all the C files that want to use that, put:
$include "xyzzy.h"
and, in one of those C files, also put:
int xyzzy; // define it here, once.
You can think of declaration as a simple "I declare that this exists somewhere, just not here", while definition is "I an creating this here and now".
Declare extern usigned char exitStatus in Global.h and define it in one implementation file.
The problem is during the linking phase; include guards in the headers won't help you.
In C, there is the separate concepts of declarations and definitions. Declarations are what are put into headers; they merely state that a particular variable exists. The definition of a variable is where storage is actually allocated for it.
For example, in your Global.h, you have:
#ifndef Global_h
#define Global_h
#include <iostream>
usigned char exitStatus;
#endif
This is defining a variable called exitStatus, and the linker is complaining because any given variable should only be defined in one place in a program. What you need to do is declare it in the header, and then define it in only one place in a source (*.cpp) file. For example, your header should declare exitStatus with:
extern char exitStatus;
and in only one source file, define it with:
char exitStatus;
The situation is similar for output in Root.h, as well as any other place you should be declaring variables in the header file.
See also: http://www.cprogramming.com/declare_vs_define.html