Damn include guards!!

Started by
21 comments, last by wforl 15 years, 11 months ago
Okay so I'm having some problems with my include guards and I have no idea what I'm doing wrong. Heres the situation: got 2 header files: Globals.h : stores all variables common to several modules. Graphics.h : stores functions and variables that have to do with the display. 2 source files main.cpp : app entry point and main loop. graphics.cpp: implementation of graphics.h functions. now both main.cpp and graphics.h #include globals.h so obviously there gonna be a multiple symbol problem here so I put in some include guards: 1. I place #pragma once at the very top of both globals.h and graphics.h, I use MS visual c++ express 2008 so it should work, but alas, I still get link errors because main.cpp is including globals.h when graphics.h has already included it. 2. I place all functions and variables in global.h between: #ifndef GLOBAL_H #define GLOBAL_H *global.h variables and functions go here* #endif and still i get link problems when globals.h is included twice, what am I doing wrong? Please help Thanks
Advertisement
First is that you have a "Globals.h" :P
you never/rarely need globals


does Graphics.h include Globals.h ? or vice versa ?
Quote:Original post by LittleJimmy
and still i get link problems when globals.h is included twice

What link problems?

You're probably violating the ODR (one definition rule). Don't DEFINE your variables in the header, merely DECLARE them. Example:

globals.h
extern int global_int;

globals.cpp
int global_int;

Well, you said you got linker errors.
That means that you have multiple symbols defined in several modules.
This has nothing to do with all that include stuff:

int i;int i; // will fail during compile time: error C2086: 'int i' : redefinition e:\code\library\test\test.cpp(4) : see declaration of 'i'


So, but what is this linker error?

Lets say, you've got two modules:
main.cpp and Graphics.cpp
If you have a header that defines all the globals like
//Myheader.hint screenwidth;bool fullscreen;

And you include that stuff in BOTH modules, you will obviosly get linker errors, because ANY global can only exist ONE time in your whole project. If you want to share globals between modules, you need to do it like this:
//Main.cppint screenwidth;bool fullscreen;//Graphics.cppextern int screenwidth;extern bool fullscreen;

This is the right way to share them. The compiler will know that when he parses Graphics.cpp, that these globals are stored elsewhere and the linker won't complain, because he knows that there is only ONE int screenwidth defined.

Hope I could help.

*edit* To slow :((
Your inclusion guards don't work because they do not do what you think they do.

Check out this EXCELLENT read on the topic: http://www.gamedev.net/reference/articles/article1798.asp

should clear everything up, did for me at least :D
Comrade, Listen! The Glorious Commonwealth's first Airship has been compromised! Who is the saboteur? Who can be saved? Uncover what the passengers are hiding and write the grisly conclusion of its final hours in an open-ended, player-driven adventure. Dziekujemy! -- Karaski: What Goes Up...
Hmmm... okay well I've read the article (did it before I came here) so I'm obviously not getting something.

so I should extern the variables and define them in every header that uses it?

oh and graphics.h includes globals.h, and globals.h includes periphery headers such as windows.h and the directx headers and what not.

I have one global engine class that my main loop is going to access for display/sound/input etc, now the use of the functions within that one class is going to be split up amongst several headers and their associative source files, so how do I do this when the one class does everything (sound, display, input)?

should i go back to my engine and rather split the various components into several classes or should I just create 4 different engine classes each one concentrating on a different section, or is there another way to do this, I'm pretty to all of this so I don't know much, but the last one doesnt seem too efficient.

thanks :)
I think you are confusing declaration and definition.
Let me give you an example:

struct Car{    float speed;    string Name;};


Ok. Now this is a declaration. The compiler now knows, that there is a struct that is named Car. But you cannot access any of these variables, if you don't define a variable of that type:

Car.speed = 5.0f // That will obviosly not work, Car is a type, like intCar MyCar; // Okay, now here, you have defined a variable of the type Car. You can now access the elements of that particular instance:MyCar.speed = 5.0f;


Now, regarding to your question about the design.
If you have only ONE engine class, I wouldn't declare all the member functions of that class in several files, but only in one. In general, if you create a class, put the declarations inside a header (.h) file.
// Header File: Engine.h, contains the declarationsclass CEngine{public:    void DoGraphicStuff();    void DoSoundStuff();private:    void SomeSecretFunction();};


Just as in my above example, you have declared your class and the member functions, but you have not defined them. Now, the definition of all these functions, is going to get inside Engine.cpp. In general, put the definitions of functions and member functions inside a module (.cpp file).
// Engine.cpp, contains the defitions of all the member functions#include "Engine.h"void CEngine::DoGraphicStuff(){    // Do your calculations here}void CEngine::DoSoundStuff(){}void CEngine::SomeSecretFunction(){}


Now, everything, that wants to access some function or variable of CEngine needs
1. to know the declaration of the CEngine, that is: #include "Engine.h"
2. to know wich instance of CEngine it wants to access. Now here you have several ways of doing it:
// SomeFile.cpp// #1, Get the variable to the function// It is cruical that you either pass the variable by reference (that &) or by pointer (CEngine *Engine)void SomeFunction( CEngine &Engine ){    Engine.DoSoundStuff();}// #2, The easy wayextern CEngine Enginevoid SomeFunction(){    Engine.DoSoundStuff();}

If you chose the second way, you WILL need do define a variable of type CEngine only ONCE in a module (that is, a .cpp file):
// Main.cppCEngine Engine; // The Engine variable is defined, it can be accessed in any other module, if that one does: extern CEngine Engine


I wouldn't recommend another way of doing this. I'm no expert, but I would consider it bad style, to "extern" a variable in a header you include. If a module wants to use a global variable, it just declares it as extern and voila, you have got access.

One more thing. If you want to split your engine into several files, I would recommend you create more classes. Create one sound, one graphic class, that are both members of CEngine:
class CEngine{private:    CSound Sound;    CGraphics Graphics;};
okay well my engine is exactly that shadowman, its one mediator class labelled as the engine with a bunch of delegate classes, one handling display, one handling sound etc, as its members.

Okay, let me give you a basic code snippet of what I have cos I'm trying the extern thing but it aint helping, still getting main.obj : error LNK2005: "struct HWND__ * hWnd" (?hWnd@@3PAUHWND__@@A) already defined in Graphics.obj.

I'm thinking I'm gonna need to follow molle85's advice here and find a way to get rid of these globals, but I'm very lazy :D

okay in globals.h I have the variable

HWND hWnd;

now i'm gonna use this as a global cos a few functions in other files need it.
(I should probably pass it to those functions as a parameter hey?)

now my main.cpp includes globals.h cos it contains the win32 functions to create the window.

Graphics.h includes it to create a directx device using hWnd.

so what do I add to the globals.h file so that it doesnt say:

main.obj : error LNK2005: "struct HWND__ * hWnd" (?hWnd@@3PAUHWND__@@A) already defined in Graphics.obj

when I compile.

Why am I not getting this? Is it just me?

thanks for taking trouble to help me guys.

You should never declare a variable like that in a header. You should use:

Globals.h
extern HWND hWnd;

in ONE .cpp file (Globals.cpp, preferably):
HWND hWnd;

When you #include something, you're saying to the compiler "I want you to copy and paste everything from the #included file into this file, where I put that #include line". If you think about what that means, you're pasting this line into two files:
HWND hWnd;
Which means that the variable is declares in two files. Which is the error you're getting; there's multiple definitions of that variable and the compiler doesn't know which one you want to use. It doesn't matter to it that they're both the same.

Now, if you use the "extern" method, you're now saying in two files "There is exists a variable of type HWND, called hWnd. Just so you know about it. I'll declare it later". Then, in one .cpp file you actually declare it. That ay you only have one instance of it.
Ah ya no what, screw it, will scrap the global variables and use pointers for my engine class.

C++ you win again, AARRGGH!!!

Okay so now some other problems with my engine are starting to appear now that i'm no longer using globals, man I'm such a noob :(

Okay well thanks for the help everybody, I'm a changed man now, Gonna start a new thread cos my engine broke thanks to my skill at c++ :)

This topic is closed to new replies.

Advertisement