Initialisation problems

Started by
12 comments, last by oler1s 15 years, 11 months ago
I seem to have a problem with some classes being initialised/created. I have two GUI screen classes which contain all the UI controls for that particular screen (the two in question are main screen and player select screen). I declare a static pointer to each in the .h file where their classes are defined. I then create the classes in a function:

/* Creates the User Interface screens for the menus */
inline void createUIScreens() {
    mainScreen = new MainScreen();
    playerScreen = new PlayerScreen();
    mainScreen->setVisible(true);  // Show title screen
}

setVisible simply sets the screen to draw. The problem i have is that when i try to display playerScreen, it won't work. Specifically, playerScreen is NULL. The strangest thing is that playerScreen->setVisible(true); is actually called, i don't get an access violation (null pointer exception). Both screens inherit from class Container, which is the super class for all UI windows/screens.

class Container : public Component {
    ...
    inline void setVisible(bool b) { Component::active = (b ? this : NULL); }
};


class Component {
public:
    static Component* active; // The component that is active
    ...
};

As you can probably see from the above code, active is set to the Container that calls setVisible(true). It is a pointer to the Container (screen) to draw, and is set to NULL if nothing is visible. This may not be the best way to do it but it's the way i'm doing it. My problem is that when i call playerScreen->setVisible(true);, playerScreen is NULL yet the function still get's called and (as far as i know) 'this' is NULL; When i outputted some debug values i found that playerScreen & mainScreen were NULL when initialised, then set to some value (the pointer that is) when they were created, and then went back to NULL when i called playerScreen->setVisible(true);. Any ideas? thanks
[Window Detective] - Windows UI spy utility for programmers
Advertisement
"static initialization order fiasco"
Yes, i read about that a while ago from Thinking in C++. But i didn't think that applied in my case since i call createUIScreens() from main (WinMain) and i call playerScreen->setVisible(true); after it. So i didn't think that it was an initialisation problem but it seems that it is (hence the title of my post). I should mention that i call setVisible from Windows event proc but that shouldn't matter.

EDIT: I should probably post the code for the declaration of the variables. I already mentioned that they are pointers but here is the actual code:
#ifndef _UISCREENS_H_#define _UISCREENS_H_#include "gui/gui.h"using namespace gui;class MainScreen;class PlayerPanel;class PlayerScreen;//// Declarations here //////////////////static MainScreen* mainScreen = NULL;static PlayerScreen* playerScreen = NULL;/////////////////////////////////////////class MainScreen : public Container, public ActionListener {    ...};class PlayerScreen : public Window, public ActionListener {    ...};/* Creates the User Interface screens for the menus */inline void createUIScreens() {    mainScreen = new MainScreen();    playerScreen = new PlayerScreen();    mainScreen->setVisible(true);  // Show title screen}#endif  // _UISCREENS_H_
[Window Detective] - Windows UI spy utility for programmers
static at global scope means one copy per translation unit, which means that if two different cpp files include your header they each get different copies of mainScreen and playerScreen, almost certainly not what you want. Replace static with extern and define your variables in one cpp file, or better yet, get rid of the globals altogether.

Also note that your include guard is illegal. Identifiers starting with an underscore followed by a capital letter (or containing consecutive underscores) are reserved.

Σnigma
Quote:Original post by Enigmastatic at global scope means one copy per translation unit, which means that if two different cpp files include your header they each get different copies of mainScreen and playerScreen, almost certainly not what you want. Replace static with extern and define your variables in one cpp file, or better yet, get rid of the globals altogether.

Man, there is so much i don't know about C++. I thought that static at global scope meant that the variable is only defined once instead of each time the header file is included, which is right but i didn't know that each cpp file gets a separate copy. I will try using extern and defining the variables in the respective cpp files where the classes are defined.

Quote:Original post by Enigma
Also note that your include guard is illegal. Identifiers starting with an underscore followed by a capital letter (or containing consecutive underscores) are reserved.

Really!? I have used it like that since i started programming in C++ and it has worked fine for me. Is there any compiler that it won't work on or are you just saying that it's bad programming practice? And i use the underscores at the front and back because the identifier is reserved, for header file guards. Any other capital letter identifiers are used for constants.

EDIT: yay, it worked. thanks. It's probably not the most elegant solution (extern variables defined in the cpp file where the class is defined) but it works so i'll leave it at that for now.
[Window Detective] - Windows UI spy utility for programmers
Quote:Original post by XTAL256
EDIT: yay, it worked. thanks. It's probably not the most elegant solution (extern variables defined in the cpp file where the class is defined) but it works so i'll leave it at that for now.


Elegant or not, it's the proper solution. If you only want a global variable once, it must only appear in one place. A header file is copy-and-pasted wherever it's #included so that is very unlikely to be 'one place'.

It's just the way Enigma said "...or better yet, get rid of the globals altogether" made me think that global variables weren't the best solution. Although i understand that there would be cases where it is the best and only way.
[Window Detective] - Windows UI spy utility for programmers
Getting rid of globals is best, yes. But if you want globals, putting them in a single .CPP and referencing them via an extern declaration in a header is the only reasonable approach.
Quote:Original post by XTAL256
Really!? I have used it like that since i started programming in C++ and it has worked fine for me. Is there any compiler that it won't work on or are you just saying that it's bad programming practice? And i use the underscores at the front and back because the identifier is reserved, for header file guards. Any other capital letter identifiers are used for constants.
I'm not aware of any compiler which disallows all such identifiers, but there certainly exist compilers that use identifiers like that internally and will stomp all over you if you happen to clash with them. You might never hit one of those situations, but why take the risk?

Σnigma
Quote:Original post by XTAL256
Yes, i read about that a while ago from Thinking in C++. But i didn't think that applied in my case since i call createUIScreens() from main (WinMain) and i call playerScreen->setVisible(true); after it. So i didn't think that it was an initialisation problem but it seems that it is (hence the title of my post).


Sorry to misinform, I didn't read your post closely enough :)

This topic is closed to new replies.

Advertisement