Jump to content
  • Advertisement
Sign in to follow this  
finky45

multiple definition of X

This topic is 3951 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

I need to have a "Gloabls.h" file in which I store some variables like SCREEN_WIDTH, GAME_STATE, DEBUG_LEVEL etc... so that any of my classes can use them. However having included this file in many .cpp files I get a multiple definition problem. I already used #ifndef #define and #endif. Also tried using "extern" but it doesn't work (error still comes up) + I get a warning about the variables being initialized (which they must be). I don't quite understand what extern does and how it works. I'd rather not use commands that have other implications which will require that I handle another problem later on. Is there a simple and elegant way of using the same variables in multiple .h and .cpp files?

Share this post


Link to post
Share on other sites
Advertisement
Don't do that.

Your includes guards don't protect against multiple-definitions (they are per-translation-unit only), see this article. You need to have extern T Variable; in the header, and a definition in one source file (like T Variable = OptionalInitializer) for this to work at all, although you should really try to avoid having to do it at all.

Especially since "globals" headers like that are frequently a bad idea.

Share this post


Link to post
Share on other sites
My personal recommendation is not to use globals in the first place :) Specifically a "Globals.h" master include file.

To answer your question,

Globals should be declared "extern" within the header file, and defined within the source file. For example:
//Globals.h
extern const int SCREEN_WIDTH;
//Globals.cpp
const int SCREEN_WIDTH = 800;
As long as Globals.h has inclusion guards, it should work fine.

I do have to recommend against using this setup, though.

Share this post


Link to post
Share on other sites
Okay I understand now why having global include files is not a good idea, and I'll try to stay away form doing that. However, I still don't get why having global variables is bad thing(TM).

The way I see it, I'll be using SCREEN_WIDTH quite a lot, (a couple hundred times/second) especially in my logic functions. I don't see the advantage of passing it as an argument, even if I only have to do it once in the constructor.

For example, what if I need to change one of these in the middle of running my game? Such as DEBUG_LEVEL. Then I would have to go back and write a whole new function that will change the member variable in each of the classes/functions that I use. It just seems more typing without any benefits.

But anyway, tell me why it's wrong to use global variables since I can't think of any reason why.

Also Crypter,

I can't use "const" in my globals. The whole idea is to be able to change that variable then have all of my functions and classes use the new value without calling any extra function.

Share this post


Link to post
Share on other sites
Quote:
Original post by finky45
tell me why it's wrong to use global variables

It's impossible to reason about when global state gets changed.

Share this post


Link to post
Share on other sites
Quote:
Original post by finky45
The way I see it, I'll be using SCREEN_WIDTH quite a lot, (a couple hundred times/second) especially in my logic functions. I don't see the advantage of passing it as an argument, even if I only have to do it once in the constructor.


Accessing a variable hundred times per second is ridiculously small, and certainly too small to have any kind of performance worries. Think about it: rendering a single 32*32 sprite every frame will be at least a thousand times more costly, performance-wise, than accessing a single variable.

Unless you're working on extremely tight inner loops, don't let micro-optimization considerations affect your design.

Quote:
For example, what if I need to change one of these in the middle of running my game? Such as DEBUG_LEVEL. Then I would have to go back and write a whole new function that will change the member variable in each of the classes/functions that I use. It just seems more typing without any benefits.


You should encapsulate debugging tools in a class of their own, instead of having a modifiable DEBUG_LEVEL variable floating around. Pass that class by reference. You won't have to write new functions to alter that instance's behavior, thanks to the reference semantics.

Quote:
But anyway, tell me why it's wrong to use global variables since I can't think of any reason why.


Global variables generate coupling. Increased coupling makes refactoring and code reuse harder, which results in slower development time.

A clear example? For instance, as they are laid out now, all functions which rely on a viewport width use the SCREEN_WIDTH variable, which means that they all implicitly use the same width. If you wanted to render to a smaller viewport (for instance, to implement a split-screen mode, or to run a game demo in the main menu) or to increase the viewport dimensions for logic purposes (for instance, enemy homing missiles being allowed to stay outside the screen for a certain small distance), then you would have to do some heavy rewriting of these functions so that they can use a different variable. Invariably, changing code always takes longer than writing the code correctly in the first place, so that's a loss of time for you.

A more subtle example? The state management code related to GAME_STATE is certainly quite similar to state-based AI for your opponents, or perhaps to the state-based kernel used in your menus. By having that code explicitly mention GAME_STATE, you prevent its reuse as part of the other state-based systems, which means that you will have to write the same functionality two or three times instead of just one, which is quite wasteful. By making your state-management code parametric, you don't have to write that much additional code (typically one or two additional lines) but you can save one or two rewrites of the repeating functionality.

Share this post


Link to post
Share on other sites
Quote:
Original post by DevFred
Quote:
Original post by finky45
tell me why it's wrong to use global variables

It's impossible to reason about when global state gets changed.


That sentence confuses me.

Maybe I didn't make my problem clear. I want to declare variable X=3 in one place only (preferably in "Globals.h". I want my classes to use X for whatever reason. Then I will make X=4 in a some class. All of my classes should then recognize X being equal to 4.

You know when you declare say "int number=0;" outside of main? Then main knows what it is? How can I do that for all my other .cpp files?

...

Share this post


Link to post
Share on other sites
Quote:
Original post by finky45
That sentence confuses me.


What he means is that, when you look at a global variable after a few weeks, you can't easily tell which functions will change it, when they will change it, and why they will change it.

For instance, suppose that as part of your update step, a function changes the game-state. Would that interrupt the update step? If it does, is it really a great idea to allow a function to skip the execution of an unspecified amount and kind of other functions? If it doesn't, how do you cope with the fact that, as a function is called as part of game state 'A', the game state might have been changed to 'B' or even something else? Will you keep that volatility of the game state in mind whenever you write a function that somehow depends on the current game state?

Share this post


Link to post
Share on other sites
Quote:

The way I see it, I'll be using SCREEN_WIDTH quite a lot, (a couple hundred times/second) especially in my logic functions. I don't see the advantage of passing it as an argument, even if I only have to do it once in the constructor.

globals do not have that much, if any, speed advantage over member variables. The purpose of encapsulating variables behind coherent interfaces that they belong to (the classes) is to help reducing complexity, and make things much easier to modify.

If you use SCREEN_WIDTH alot, and SCREEN_WIDTH is a variable, how can you insure that the value stored in SCREEN_WIDTH is valid? How do you know when it was modified? What happens if you change the name of the variable? How do you know what modifies the variable, and where?

Some of these questions are impossible to know with globals, as any part of the file (or other files, assuming it is externally declared) can access it. If the variable is confined within a single location, only the routines within that same confined place has access to it. This is the bases of encapsulation.

Also, even if your class where the variable is defined has a simple Get() method to retrive your SCREEN_WIDTH variable, it can be declared inline to remove the function call out.

The disadvantages of globals become apparent as your programs get larger.

Share this post


Link to post
Share on other sites
I got it to work the way I wanted based on Crypters solution.

For the sake of argument, I'll try to explain how I am building my game. The GAME_STATE represents the overall state that the game is in. It's an enum. Some states are PAUSED, EXIT etc.. Right now, the only functionality it has is EXIT. If the state is EXIT, then my main will not perform the game loop any longer and will proceed to clean up the game then close.

I want to be able to set the state in my functions which are logic, input, and render. For example if an unrecoverable error occurs in any of my functions then it would tell the game, "okay we need to quit". It sets the STATE to EXIT, reports the error in a file somewhere and then main takes care of the rest.

With proper documentation, I can easily see which function set the state to EXIT, and why. Is it the only way to do it? Obviously not, but it makes sense to me as being easy. The best way? You guys seem to think it's not probably because you have more experience than I do, but I don't see a problem so far.

In my main I have:


cMetalist* metalist = new cMetalist();
cInput* input = new cInput(SCREEN_WIDTH, SCREEN_HEIGHT);
cLogic* logic = new cLogic();
cRender* renderer = new cRender (SCREEN_WIDTH, SCREEN_HEIGHT);

//more crap here

while ( STATE != EXIT )
{
input->Perform( metalist, param1, param2, param3, param4 );
logic->Perform( metalist, param1, param2, param3, param4 );
renderer->Perform( metalist, param1, param2, param3, param4 );
};



See how I have to specify SCREEN_WIDTH and SCREEN_HEIGHT for each class? They need to know that in order to work. Well what happens if I have to change it? Then I need to create get and set functions, then call them in main... etc.. possibly have to recreate the framework objects which I don't even know if they'll work right.

I used to have return types for each of these functions, but that only returned one variable. If I wanted more then I would have to pass parameters. Some were global some were not. The calls would get really long and I hated having to type all that.

The way my game is designed so far, global variables make a lot of sense to me. Its my first game where I try to keep things separate, and this is how I chose to do it. I'm learning from mistakes as I go and rewriting code as I go, and taking forever but I'm learning form it.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!