Making variables global throughout the whole application

Started by
7 comments, last by okonomiyaki 20 years, 8 months ago
I''m trying to figure out the best way to do this. I want some variables to be global throughout the whole application, so that any class in whatever instance can access them. My first idea was to create a class that encapsulated the info, and every variable was "static". Whenever I wanted to access these variables, I just did a GameInfo::lightPos. But when I compiled, I got several linker errors saying all the static members were unresolved. Second, I tried to simple declare them in stdafx.h. I figured that this was the top-level place where it would be truly global. I compiled, and since stdafx.h is included in the top of every .cpp file, I got a lot of "already been declared." So I added an #if !defined(GLOBAL_CONSTANTS) #define GLOBAL_CONSTANTS ... //declare #endif but that didn''t help, I still got a lot of the "already been declared" errors. What would be the best way to do this?
Advertisement
Take it out of stdafx.h.

Next, create a GameInfo.cpp file (or whatever your header file is with a .cpp extension).

For each static member variable in your class declaration (i.e. the header), you''ll have to do something like this:

LightPosition GameInfo::lightPos;

If it''s a pointer, it''s usually a good idea to set it to NULL. If it''s a number of some type, it''s a good idea to set it to something meaningful.
have every file including a header, externals.h would be a suitable name. In there put every variable you want to be able to access.

extern int iGlobal;
extern float fGlobal;

etc...
APE
I find it hard to believe that you would need all of your globals in all of your source files. You should be able to access them by including the relevant (not all-inclusive) header files if you really truly need them.

______________________________________________________________
The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ
MySite
______________________________________________________________
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
quote:Original post by okonomiyaki
I''m trying to figure out the best way to do this.
I want some variables to be global throughout the whole application, so that any class in whatever instance can access them.
My first idea was to create a class that encapsulated the info, and every variable was "static". Whenever I wanted to access these variables, I just did a GameInfo::lightPos. But when I compiled, I got several linker errors saying all the static members were unresolved.
Second, I tried to simple declare them in stdafx.h. I figured that this was the top-level place where it would be truly global. I compiled, and since stdafx.h is included in the top of every .cpp file, I got a lot of "already been declared." So I added an
#if !defined(GLOBAL_CONSTANTS)
#define GLOBAL_CONSTANTS
... //declare
#endif

but that didn''t help, I still got a lot of the "already been declared" errors.

What would be the best way to do this?


You can do classes with static variables like so:

class MyClass{public:  static int myInt;};int MyClass::myInt = 0; 


Also, to avoid a hastle like this, I wrote my own template wrapper that takes a class as input and creates it once, and deletes it once nothing is using it anymore. This also helps me initialize stuff: classes depending on certain functionality can use this same class to ensure the code is running.

The template:

template< class T > class SystemReference{private:	static T * data;	static unsigned int references;public:	T *operator->(void) { return data; }	SystemReference( void )	{		++references;		if (! data) data = new T;	}	~SystemReference( void )	{		if ( (!--references) && data )		{			delete data;			data = 0;		}	}};template < class T > T * SystemReference< T >::data = 0;template < class T > unsigned int SystemReference< T >::references = 0; 


note the template versions of the initialization code

I wrap _EVERYTHING_ in ifdef statements using a naming scheme. For example, that template was wrapped inside:

#ifndef _PANDARIX_SYSTEM_HPP_
#define _PANDARIX_SYSTEM_HPP_

...

#endif //ndef _PANDARIX_SYSTEM_HPP_

Examples of classes of mine using the above template:

namespace System{	namespace _SysClass	{		class SDL		{		public:			SDL( void );			~SDL( void );		};	}	typedef SystemReference< _SysClass::SDL > SDL;	namespace _SysClass	{		class Screen		{		public:			Screen( void );			~Screen( void );			void Set( unsigned int w , unsigned int h , unsigned int bpp );		private:			System::SDL sysSDL;		};	}	typedef SystemReference< _SysClass::Screen > Screen;}

The SDL constructor calls for example: SDL_Init( SDL_INIT_EVERYTHING ) while the destructor calls SDL_Quit();

Then, the Screen class contains the typedef''d wrapper, so that when a screen is created, if SDL is not initialized, it is initialized. Thus, I can write my main function like so:

int main( int argc , char ** argv )
{
System::Screen Screen;
Screen->Set(640,480,32);
}

when the program ends, the screen class goes out of scope, causing the SDL class to go down to 0 references, having it delete itself, finishing the de-initialization.

I''d post more but I have to go to work
Ah, great!
Thanks a lot for all your suggestions. I ended up using AP''s suggestion because it was the easiest to implement at the moment. It''s working, but I really have no idea why. You have to implement a variable?
And thanks for the detailed explanation MaulingMonkey, I''ll probably play around with ways to do it later on and implement your version, or maybe the other one suggested, to see which one I like better.
Thanks a lot!
quote:Original post by okonomiyaki
Ah, great!
Thanks a lot for all your suggestions. I ended up using AP''s suggestion because it was the easiest to implement at the moment. It''s working, but I really have no idea why. You have to implement a variable?
And thanks for the detailed explanation MaulingMonkey, I''ll probably play around with ways to do it later on and implement your version, or maybe the other one suggested, to see which one I like better.
Thanks a lot!


No prob...mainly just copy ''n paste .

As for the errors, I''ll do a quick rundown:

Your original case:
The ''static'' declerations are akin to the extern keyword in some ways. That is, it declares the reference to the variable, but is not the actual variable data decleration. This is what the int ClassName::MyIntVar; line does - it declares the actual data.

The second case:
The problem with declaring it withing stdafx.h as it sounds like you did/I''m guessing you did, is that the decleration gets included multiple times... and the errors are generated under the same logic as:

int main ( ... ){  int myvar; //ok...  int myvar; //error: repeat decleration} 


only instead of variables within a function, your problem was multiple classes in the global namespace.

The defined method should work...hmm... I''m not sure how your defined macro is setup, so it might be in err when dealing with defines that don''t have a value. Defining GLOBAL_CONSTANTS as 1 might fix the problem in that case, or using:

#ifndef GLOBAL_CONSTANTS#define GLOBAL_CONSTANTS//....#endif 


You don''t have to use a variable, but I find it''s a nice way to deal with stuff...at least for most things, for me .

As for the file combination, you could try something like:

stdafx.hextern int fnord;extern char ghesuntight; //<-- decleration of referencemain.c(pp)#include <stdafx.h>int main ( int argc , char **argv ){  fnord = 4;  ghesuntight = "!";}data.c(pp)#include <stdafx.h>int fnord; //decleration of datachar ghesuntight; 


Time to go pick up garlic bread for dinner
Ah, thank you very much. Yeah, I was wondering why the defined method didn''t work.. haven''t done too much with precompiled defines, maybe I set it up wrong.
Ah well, it''s working for now. I''ll see if like the current system enough or if I should upgrade to yours
The extern keywork sometimes confuses, but I see how it works. It''s an interesting way of doing things.
quote:Original post by okonomiyaki
Ah, thank you very much. Yeah, I was wondering why the defined method didn''t work.. haven''t done too much with precompiled defines, maybe I set it up wrong.
Ah well, it''s working for now. I''ll see if like the current system enough or if I should upgrade to yours
The extern keywork sometimes confuses, but I see how it works. It''s an interesting way of doing things.


extern confused me at first too... pretty much, read it as ''this exists''. Extern is to variables what prototypes are to functions:

main.cppextern int fnord;int fnordus_function( void );int main( int argc , char ** argv ){  fnord = fnordus_function();} 


*****

fnordus.cppint fnord = 10;int fnordus_function( void ){  return 5;} 

This topic is closed to new replies.

Advertisement