Sign in to follow this  
taz0010

Best way to construct and destroy static objects

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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".

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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