Best way to construct and destroy static objects

Started by
6 comments, last by taz0010 14 years, 2 months ago
I have a class that needs to make an API call. (specifically to the Windows RegisterClassEx function) The function needs to be called once, and only once, and the single instance should be deleted (by calling UnregisterClass) when the program is shut down. The RegisterClassEx function requires a HINSTANCE parameter so I can't make the API calls at static initialisation time. I'm thinking of wrapping the API calls in a class, creating a static instance of it, and setting it's isInit flag to false. Then whenever I create an instance of a certain object, I check whether the wrapper has been initialised yet. If it hasn't then I call RegisterClassEx. The destructor calls UnregisterClass if the isInit flag is true, which takes care of releasing the memory. But is this the easiest way to handle this sort of problem? And am I wasting my time using "clean up" API calls when the program is ending and Windows will automatically reclaim the memory anyway?
Advertisement
Is there a reason the class needs to be statically initialized? Why can't you just create an instance near the beginning of WinMain which registers the window, and destroy it near the end of WinMain to unregister the window? If every instance you create tries to register a window class, then you can use GetClassInfoEx to see if the class is already registered and skip the registration if it is.
It's a library class which I can make use of in other programs. It wouldn't be very good design to have to manually call init() and release() before using certain objects from the library.
Quote:Original post by taz0010
It's a library class which I can make use of in other programs. It wouldn't be very good design to have to manually call init() and release() before using certain objects from the library.


#include "library.hpp"int main(){    library::context theContext(/* pass your HINSTANCE, etc. */);    /* do other things */    /* at the end, theContext is destroyed and the destructor       will do whatever it needs to do */}

Your documentation could say something along the lines of "it is required that one creates a context instance before using any other objects, and that the context instance outlives any other objects".
Quote:Original post by taz0010
It's a library class which I can make use of in other programs. It wouldn't be very good design to have to manually call init() and release() before using certain objects from the library.

It is actually a VERY good design to have to do that.

The bad thing is having libraries perform a ton of work before main() is even hit.

Libraries will often need or at least accept a bunch of parameters with initialization.

Two very common parameters are a memory allocator and a logging function.

You really need a memory manager so you can allocate from a pool or other resource that the game provides. Allocating from the OS is incredibly slow, so if the game gives you a pool you should gratefully accept it.

Logging to a location the game specifies allows the game to do something useful with the log, rather than assuming that the library knows best how to handle logging in all situations.

Finally, global statics mean that your game cannot create additional instances. This is rarely a good thing. If the game wants to create a static instance for themselves they can, in addition to any non-static versions. But for you to force the bad design upon them is a very bad decision.
What NullSquared said ... do it RIIA-style, call RegisterWndClass in the constructor of an object of some class, Unregister in the destructor, and instantiate the class in your WinMain.

FYI, I wrote a wrapper around the Win32 GUI stuff before, and I actually hid calls to RegisterWindow from the user of the library. If the user was creating a custom window they would just subclass a generic custom window object and provide the class name to the base class constructor. The library would figure out whether it needed to register it. If you're doing something similar, this is another way to go.
Quote:Original post by taz0010
It's a library class which I can make use of in other programs. It wouldn't be very good design to have to manually call init() and release() before using certain objects from the library.


No, you've got that backwards; the MORE control the calling app has the better.
Quote:It is actually a VERY good design to have to do that.

The bad thing is having libraries perform a ton of work before main() is even hit.

Libraries will often need or at least accept a bunch of parameters with initialization.


I ended up having the library register the Window class *once*, in the constructor of the first window instance that uses it. And yeah it does involve passing a hInstance in. You don't pay for what you don't use.

Quote:Finally, global statics mean that your game cannot create additional instances. This is rarely a good thing. If the game wants to create a static instance for themselves they can, in addition to any non-static versions. But for you to force the bad design upon them is a very bad decision.

The global static in question is just a wrapper class that records whether the API call has been made yet. The call really does only need to be made once. The Windows API is not object oriented, and if RegisterClassEx tries to create the same object twice, from anywhere in the program, it returns an error. But once you call RegisterClassEx, you're free to create as many instances of the actual window as you like.

This topic is closed to new replies.

Advertisement