Self-storing class-instances on creation

Started by
10 comments, last by dilyan_rusev 11 years, 7 months ago
Hello,

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


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 }


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)
Advertisement
There can only be one QApplication (actually a QCoreApplication) object in an application and that counts as a singleton, accessible via QCoreApplication::instance.
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?
No, this is a case where a singleton was used. It doesn't make it right, nor does it mean it is absolutely wrong. It was a design decision by the QT team. It would be interesting to know if the team would choose this design now, were they free of any backward compatibility constraints.

Design is a subtle art, particularly when one is designing a complex public API that will be consumed by thousands of applications. The problem with singletons is that they are extremely attractive to design beginners, because they "solve" all those complex issues of lifetime and communication. Someone with design experience will realise the solution involves side stepping these important questions. This is convenient in the short term, but eventually these questions will demand an answer. Trying to retrofit a coherent answer into an existing codebase is not a trivial task.
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..?
One thing to keep in mind is that everything doesn't have 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.
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 :)
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.

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?


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.

- 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


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.

This topic is closed to new replies.

Advertisement