Sign in to follow this  

On Static Class/Global Variables [Resolved]

This topic is 4271 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've had this problem before and I have it fixed, but I'm not sure how reliable the fix really is. In short here's what's happening. I have a cInput class that is used to handle input in SDL. Unlike conventional systems, there can be multiple cInput objects at any given time for different functionalities. In order to have the nicest, simplest, most user friendly design, I must use SDL's event filter to automatically pass events to all cInput objects. Since at any time I don't know the actual cInput objects, the cInput class maintains a static vector of all objects. The cInput ctor will add that object to the vector and the dtor will remove it from the vector. This works fine, except when a global cInput variable exists. In that case, the ctor will end up being called before the cInput's static vector is instantiated, so the object is not tracked. I can fix this by #including the .cpp directly into the main.cpp file. That way, as from what I have seen, the the cInput's static vector seems to be always instantiated before any other global cInput variables. Of course, this seems kinda bleh. I do not know for a fact that by doing this the static class vector will always be instantiated before any other global cInput variables. The only other alternative I see is to add another member function to the cInput class tha the user must call, something like Register() to track it. The only reason I did not want to do that is because of the additional "inconvience" it adds. Is it guaranteed that the static class vector will always be created before any other cInput objects? If not, is there any better way of going about this that I am not seeing? I don't mind having to add more code to make the process more automated, all I am after is ease of use and simplicity. Pretty much making this a plug and play component that can be added to any SDL project without modifiny existing code or requiring too much for setup. Right now this is what a demo looks like:
#include "cInput.h"

using namespace std;

// Input object
cInput myInput;

int main(int argc, char* argv[])
{
	bool done = false;
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_Surface* screen = SDL_SetVideoMode(640, 480, 0, SDL_DOUBLEBUF);

	// Create the input
	cInput::Create();

	// Since 'myInput' is global, we have to register it with the cInput class
	cInput::Register(&myInput);

	while(!done)
	{
		SDL_Event Event;
		while(SDL_PollEvent(&Event))
		{
			if(Event.type == SDL_QUIT)
				done = true;
		}

		if(myInput.IsKeyDown(SDLK_ESCAPE))
			done = true;

		if(myInput.IsKeyDown('Q'))
			done = true;

		// Clear the screen
		SDL_FillRect(screen, 0, 0);

		// Flip the screen
		SDL_Flip(screen);
	}

	SDL_Quit();
	return 0;
}


Where I'd like to get it to simply, although I do have another problem (which is what the ::Create function fixes hehe):
#include "cInput.h"

using namespace std;

// Input object
cInput myInput;

int main(int argc, char* argv[])
{
	bool done = false;
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_Surface* screen = SDL_SetVideoMode(640, 480, 0, SDL_DOUBLEBUF);

        // Create the input
	// cInput::Create();

	while(!done)
	{
		SDL_Event Event;
		while(SDL_PollEvent(&Event))
		{
			if(Event.type == SDL_QUIT)
				done = true;
		}

		if(myInput.IsKeyDown(SDLK_ESCAPE))
			done = true;

		if(myInput.IsKeyDown('Q'))
			done = true;

		// Clear the screen
		SDL_FillRect(screen, 0, 0);

		// Flip the screen
		SDL_Flip(screen);
	}

	SDL_Quit();
	return 0;
}


Thanks ahead of time for any advice, tips, or tricks [smile] If you need any more information, just let me know.
Just fot additional information, the way the input class is setup is so that the user can derive from it and create their own custom input handling classes as needed for their game. The simplest example of how this is applied is as follows: Imagine tic-tac-toe. You can use the numpad to select where to make your mark at. This is the regular "game input". Let's say you win and are brought to a screen where you can enter your name. This is "user input" and must be handeled seperately. Rather than having to code in all of the logics for two various systems using only one class, with my design, you can just have two different input classes and deactivate one and activate the other so the new system of input is now being used. When you are done entering your name, the "user input" system is deactivated and the "game input" is activated once again. Now take this concept and extend it to a larger game and it just makes life easier [wink] (or at least, I hope, haven't tested it all our yet) [Edited by - Drew_Benton on April 3, 2006 4:17:35 PM]

Share this post


Link to post
Share on other sites
I've done such auto-registering by c'tor also, but I don't access the global registry itself but by a one-shot factory routine (in fact that routine creates a singleton like vector). So the instance is build just-in-time on the first access.


namespace {
static std::vector<cInput>* _registry;
}

std::vector<cInput>& registry() {
if(!_registry) {
_registry = new ...
}
return *_registry;
}

cInput::cInput() {
registry().add(...);
}



I think also this variant works, but I'm not sure.

std::vector<cInput>& registry() {
static std::vector<cInput> _registry;
return _registry;
}

cInput::cInput() {
registry().add(...);
}

Share this post


Link to post
Share on other sites
Quote:
Original post by haegarr
I've done such auto-registering by c'tor also, but I don't access the global registry itself but by a one-shot factory routine (in fact that routine creates a singleton like vector). So the instance is build just-in-time on the first access.

*** Source Snippet Removed ***

I think also this variant works, but I'm not sure.
*** Source Snippet Removed ***


Oh wow, hmmm. I was thinking about using something like a singleton or variants similarily to what you have done, but I was looking at it the wrong way. At first I read your post and thought you were suggesting a factory design, but before I replyed, I re-read it and now I see what you mean. Let me just say, brilliant! I moved the vector out of the class and put it into a function like you showed, then added in the changes of the ctor/dtor calls to use that function. It works perfectly, thanks a lot! [smile] I just have to find a nicer way to do two more things, but that was the biggest problem.

(Oh and for reference, I used the second snippets idea)

Share this post


Link to post
Share on other sites

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