• Advertisement
Sign in to follow this  

Self-storing class-instances on creation

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

Hello,

when having a closer look at libaries like Qt, I've noticed some of them works like this:

[CODE]
1 #include <QApplication>
2 #include <QTextEdit>
3
4 int main(int argv, char **args)
5 {
6 QApplication app(argv, args);
7
8 QTextEdit textEdit;
9 textEdit.show();
10
11 return app.exec();
12 }
[/CODE]

So although there is no direct relation between app and textedit, app somehow knows that I created textEdit, as on calling app.exec() it will dispatch events to textEdit. How does that work? The only way I can think about is, having a static function registerWidget and a static vector<>-structure in QApplication, and in the Constructor of QTextEdit (or any widget) it calls QApplication::registerWidget(self). Is this ok to do so or is there any better way to do this? (not talking about gui-libaries but this self-storing/registering thing in general)

Share this post


Link to post
Share on other sites
Advertisement
There can only be one QApplication (actually a QCoreApplication) object in an application and that counts as a singleton, accessible via QCoreApplication::instance.

Share this post


Link to post
Share on other sites
Isn't singleton a bad design pattern? What I've read until now always said singletons should be avoided at any cost, so this is a case where a singleton should be used, right?

Share this post


Link to post
Share on other sites
Ok, I see that this anwser cannot be given as trivial as I thought.

But, say I want to write a small gui-libary myself. It would be only used by me, and I want it to be reusable for different projects. The main usage would be to build game-editor(s) and maybe ingame-huds. My objects need to be registered to a class that dispatches events to them, etc.. . I'd prefer having the objects automatically registered on creation. What are my options here? I see the following:

- Singleton and having the objects register themselfs (I don't really see any downside in my current design plan with this)
- A factory class that registers objects on creation
- Having to register objects manually

So uhm.. I personally like the idea of the singleton, like you said, its very tempting to me as being unexperienced with good code design. What would you suggest me to do? What pays out the most on long-term? Not specially the three cases I wrote here, I'd really like to hear about some different design patterns for this, if there are any..? Edited by The King2

Share this post


Link to post
Share on other sites
One thing to keep in mind is that everything doesn't [i]have [/i] to be an object. If some collection of functions and data is related, then it's often useful to group them together, but you should really consider whether it makes sense to create one. If clients of the gui management code will likely only use one or two methods (register, unregister?) then you don't have to wrap that functionality into an object to be instantiated, especially if doing so would require you to provide static functions anyway.
On the other hand, if you really do think there are enough operations and data to justify defining an object, and it does in fact make sense to instantiate one, then by avoiding singletons you actually gain a lot of flexibility (one lightweight gui manager handles the hud, another for the pause screen menus).
I think if you embrace the fact that a single program can incorporate multiple paradigms, you should see the need for singletons decline.

Share this post


Link to post
Share on other sites
[quote]If clients of the gui management code will likely only use one or two methods (register, unregister?) then you don't have to wrap that functionality into an object to be instantiated, especially if doing so would require you to provide static functions anyway.[/quote]

You are right, my clients are only going to use a fair minimum of methods, aside from register/unregister I have a method to distribute events, as well as some setter-methods for different focus situations. Since I won't need more than one manager too, I quess I really don't need an instanced object at all. So I'll go with a class providing static functions instead, this should fit my needs.

Thanks for the help :)

Share this post


Link to post
Share on other sites
Globals smell, but sometimes all the alternatives stink worse.

Unless someone's solved the "log errors in app consistently" problem in a simple, concise, and non-abusable way. If it has been solved, it's never been mentioned in any thread on the issue I've seen, which, admittedly, isn't all of them.

Edit: Seriously, if it has, I'd like to know. Edited by Narf the Mouse

Share this post


Link to post
Share on other sites
[quote name='The King2' timestamp='1345819613' post='4972999']
What I've read until now always said singletons should be avoided at any cost, so this is a case where a singleton should be used, right?
[/quote]

No, you should not avoid them at any cost. You should avoid them when they would put unnecessary restrictions on your application, or the cost of avoiding them is more expensive than the cost of using them.

QCoreApplication is at it's core an interface between the application and the operating system. It does not make sense to have more than one such object in your application. It is also an object manager in that it maintains a collection of all QObjects in the application and supports sending events between them.

A case can be made that it could be useful to have more than one object manager in an application. And that is true, but having a master QCoreApplication that maintains a collection of all objects in the application does not preclude you from having separate object managers that manage distinct collections of objects. In fact QObject is itself a manager of other QObjects, so it's a trivial matter to create as many object managers or window managers as you want, while at the same time having the one master manager that can handle things like shutdown events from the operating system and then send out messages to everything else in the application to ensure that it's shut down gracefully where possible.

And perhaps more importantly in this case, having a singleton QApplication as the top level window manager helps make the Qt library more user friendly, and that is at the core of the design principles behind Qt.

Share this post


Link to post
Share on other sites
[quote name='The King2' timestamp='1345822768' post='4973014']
- Singleton and having the objects register themselfs (I don't really see any downside in my current design plan with this)
- A factory class that registers objects on creation
- Having to register objects manually
[/quote]

I'll add one which I believe is more modern style RAII approach compared to other suggestions here:
- Objects register themselves to a registry, which is passed in to their constructors. And unregisters at destruction. No static objects nor static functions required.

Share this post


Link to post
Share on other sites
[quote name='Narf the Mouse' timestamp='1345842584' post='4973119']
Unless someone's solved the "log errors in app consistently" problem in a simple, concise, and non-abusable way. If it has been solved, it's never been mentioned in any thread on the issue I've seen, which, admittedly, isn't all of them.
[/quote]

What do you mean by "log errors in app consistensy"? How does that come into play when using globals?

[quote name='krippy2k8' timestamp='1345847991' post='4973129']
And perhaps more importantly in this case, having a singleton QApplication as the top level window manager helps make the Qt library more user friendly, and that is at the core of the design principles behind Qt.
[/quote]

Yeah, making the libary user-friendly is important for me too. I don't want having to screw around when creating my objects too much.

[quote name='Codarki' timestamp='1345876096' post='4973209']
I'll add one which I believe is more modern style RAII approach compared to other suggestions here:
- Objects register themselves to a registry, which is passed in to their constructors. And unregisters at destruction. No static objects nor static functions required.
[/quote]

Hmm yeah the only downside is that I have to pass the registry to whatever place I want to create a object. You'r talking about storing the register in the object so it can unregister on destruction, right? I wouldn't be delighted having to pass the registry every time before destructor is called..

So after all I quess a static function-class is really the way for me to go. It doesn't restrict me in my design plans, and it makes things much easier.

Share this post


Link to post
Share on other sites
If you are using C++, you can't just give up objects, because of all the memory management and exception safety "happiness". I don't really know any other sane way for managing resources other than RAII.

When it comes to singletons, I think their shortcomings are kind of exaggerated. I feel like this is one of those things that small kids are told not to do (like don't pee in your pants). Most of the time, it's just that programmers with experience that keep on preaching it's bad (cause it's one of those widely accepted things like "don't use goto") to get recognition from peers. And since everybody happily agrees, newbies don't get to have a coherent explanation as to why - they are often left with a list of "don't-s".

The singleton pattern is very useful, because it allows you to guard the access to global variables. The idea with patterns is that you shouldn't take them too seriously. They are just solutions to problems, usually making the least evil possible in a bad situation. You should, rather, take the core idea and modify it to suit your case. A slight variation of the singleton pattern is the immutable object, which is universally accepted as a good thing. Or your singleton can be unique per thread, per GUI window, per player, etc.

The worst thing about singletons is that they make your API hard to discover, since you have to know they exist. Also, they are very difficult to change. This applies not just to singletons, but to any static method that you have to know that has to be called at any point. Static methods are an abomination, IMO, but since some language authors decided that "thou shalt only have objects", it is the only way to have global functions.

About your UI dilemma - I'd suggest data-driven UI. Make up an XML or JSON schema and define your UI in it. If you are punished to use C++, you'll have to have some pure abstract class for registering actions that get invoked in the XML, so that your UI loader would be something like loadUI(fileName, callbackHandler). The callback handler would respond to any action invoked in the declarative UI by name. In languages that support metadata (or if you make UI logic as DLL plugins in C++), you'd just dynamically load the callbacks. That's how I'd do it, since I've grown to like declarative programming, I really think it allows you to experiment with UI options much more than "normal" code that has to be recompiled. And since it's data-driven, you can employ RAII and stuff as much as you want in the reader.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement