Sign in to follow this  

Damn include guards!!

This topic is 3487 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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;

Share this post


Link to post
Share on other sites
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.h
int 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.cpp
int screenwidth;
bool fullscreen;

//Graphics.cpp
extern 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 :((

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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 :)

Share this post


Link to post
Share on other sites
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 int

Car 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 declarations
class 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 way
extern CEngine Engine

void 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.cpp
CEngine 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;
};



Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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++ :)

Share this post


Link to post
Share on other sites
Maybe you should just start to read what we are trying to tell you. We have no multiple times told you how to solve your problems, but you don't seem to listen to any of us. Just do as Evil Steve said and you won't have problems with multiple defined symbols anymore...

Share this post


Link to post
Share on other sites
Quote:
Original post by LittleJimmy
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 :(

Eh. Your problem is not that you're a noob. Your problem is that you're a whiner. You're so consumed with complaining about how your program is not working that you're not paying attention to the instructions and solutions others are offering you. Almost everyone's program doesn't work at the beginning. So what? Fix it.

Until you can change that, you will fail to write anything of interest.

Share this post


Link to post
Share on other sites
Quote:
Original post by LittleJimmy
Yeah thats real classy guys, hurling insults and all.

They weren't "hurling insults". The problem is not that you were being insulted, but that you're a whiner. It's rare to see someone take so long to understand such a straightforward concept, and it's equally rare to see so many different posters be so patient as to continue explaining it to you. Doing less whining and more thinking will really help you in this area.

Share this post


Link to post
Share on other sites
Quote:
Original post by LittleJimmy
Yeah thats real classy guys, hurling insults and all...

No insults were hurled. The behavior you've demonstrated in this thread was merely called precisely what it is. If you've been given the solution multiple times and extensive explanations as to why, can't figure it out and just effectively throw tantrums... you're behaving like a whiny child.

Good luck with your programming career.

Share this post


Link to post
Share on other sites
I dont understand why you guys keep saying I'm a whiner, I was telling you that my program didnt work so that you guys can understand just how new I am at this (which is why I'm in the for beginners section) not because I'm whining about it, then you go ahead and say goodluck with my programming career, I think you guys just misinterpreted my message which made it seem as if I was whining, but I assure you I wasnt.

Oh and by the way, I tried to follow the intructions, which was use extern mainly, but I couldnt get it working, this is my first time im attempting to do such a large project so please try not to be so hard on me, I'm still learning.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiS-Shadowman
I think you are confusing declaration and definition.
Let me give you an example:

*** Source Snippet Removed ***

Ok. Now this is a declaration.

If that is a declaration, how come this code yields a multiple definition error?

struct Car
{
float speed;
string Name;
};

struct Car
{
float speed;
string Name;
};

// test.cpp:10: error: redefinition of `struct Car'
// test.cpp:4: error: previous definition of `struct Car'


struct Car { ... }; is obviously a definition. A declaration looks like this:
struct Car;

Quote:

Just as in my above example, you have declared your class and the member functions, but you have not defined them.

The class is defined, the member functions aren't. A class declaration looks like this:
class Engine;

Share this post


Link to post
Share on other sites
Hm, I confused that, you're right.
If that would have been a declaration, the compiler could not know, wich of multiple declarations is the one, he should use.
Hm, that just proves it, one never learns enough to master that language.
I've gotta pay more attention next time, thanks for the hint.

Share this post


Link to post
Share on other sites
Quote:
Original post by Gage64
Absolutely required reading.


It was already posted, and the original poster said he'd read it, but apparently it didn't make enough sense, since he still had "HWND hWnd;" in a header. I thought the bit under 'Fixing Problem 4' was reasonably clear, but perhaps not.

Share this post


Link to post
Share on other sites
Quote:
Original post by LittleJimmy
I dont understand why you guys keep saying I'm a whiner, I was telling you that my program didnt work so that you guys can understand just how new I am at this (which is why I'm in the for beginners section) not because I'm whining about it, then you go ahead and say goodluck with my programming career, I think you guys just misinterpreted my message which made it seem as if I was whining, but I assure you I wasnt.

Oh and by the way, I tried to follow the intructions, which was use extern mainly, but I couldnt get it working, this is my first time im attempting to do such a large project so please try not to be so hard on me, I'm still learning.

Yeah that's probably why most of the experienced developers around here always suggest beginners stick with simple stuff at first since problems like this don't usually appear until you start working on larger and more complex programs. I know in the C++ class I took in college this problem never came up since our instructor didn't even want us using multiple files for our C++ programs since it was too much work for him to keep track of all the files! I've just run into this problem splitting up a game into several source files myself so this thread has been quite helpful!

Share this post


Link to post
Share on other sites
What if’s aside, LittleJimmy now wants to create a global variable across multiple source files. We posted instructions, but he doesn’t understand or cannot fix his code. So we need to know what exactly is confusing. What isn’t working. Examples of not working. Code snippet demonstrations are extremely useful here.

Share this post


Link to post
Share on other sites
sorry for the interupted question, but under what topic in the Articles and Resources page does the following link come under

http://www.gamedev.net/reference/articles/article1798.asp

i looked under most of the programming and C/C++ titles, but couldn't see it.

I was just curious what other similar articles there were about the topic

Share this post


Link to post
Share on other sites

This topic is 3487 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this