PDA

View Full Version : Why this check ? (inst == 0)



Zingam
19th March 2011, 06:07
MyApplication* MyApplication::instance() {
static MyApplication* inst = 0;
if (inst == 0) {
inst = qobject_cast<MyApplication*>(qApp)
}
return inst;
}

I'm reading this Qt book and I've come across that example. Why do they check if inst == 0 if it is already initialized to 0?

Lykurg
19th March 2011, 08:18
Ok, that example is quite strange, because I don't see any gain in using it. But the theory is:
QPushButton* MyApplication::anyFunction() {
static QPushButton* inst = 0;
if (inst == 0) {
inst = new QPushButton();
}
return inst;
}

With that code:
* if the function never is called: No push button is created (saves you memory and time to construct).
* If the function is called the first time: You want that button, but it doesn't exist yet (this is why they check for 0) so it is created.
* If you call the function further: Because of the static declaration, no other instance is created, it simply returns the first one. (This saves you from creating a button over and over again.)

Such a construct is useful e.g. for a settings dialog, which is normally not invoked every time you use an application.

wysota
19th March 2011, 08:46
On the first glance it seems it should be:

MyApplication* MyApplication::instance() {
static MyApplication* inst = qobject_cast<MyApplication*>(qApp);
return inst;
}

I don't know if there is a deeper catch to it, maybe that it is safe to call this function before QApplication is intantiated. I can't see any other explanation.

However since QApplication already is a singleton this all should be:

MyApplication* MyApplication::instance() { return qobject_cast<MyApplication*>(qApp); }

which has an additional merit of protecting access after the application object is destroyed.

Zingam
19th March 2011, 12:50
Thank everybody for your answers. The static part seems to be the key to the answer.

Since there might be an interest in it I have decided to quote the book: "An Introduction to Design Patterns in C++ with Qt 4" available online.
It is from Chapter 15 from the PDF version, the current HTML version lacks that chapter.

http://cartan.cas.suffolk.edu/oopdocbook/

15.3 Type Identification and qobject_cast

RTTI, or Run-Time Type Identification, as its name suggests, is a system for
determining at runtime the actual type of an object, to which we may only have a
base class pointer.
In addition to C++’s RTTI operators, dynamic_cast and typeid (Section
19.8), Qt provides two mechanisms for run-time type identification.
1. qobject_cast
2. QObject::inherits()
qobject_cast is an ANSI-style typecast operator (Section 19.7). ANSI typecasts
look a lot like template functions:

DestType* qobject_cast<DestType*> ( QObject * qoptr )
A typecast operator converts an expression from one type to another, following
certain rules and restrictions imposed by the types and the language. Like other
cast operators, qobject_cast takes the destination type as a template parameter.
It returns a different-typed pointer to the same object. If at runtime the actual
pointer type cannot be converted to DestType*, then the conversion fails and the
value returned is NULL.
As the signature suggests, qobject_cast is type-restricted to arguments of
type DestType*, where DestType is derived from QObject and the class was fully
processed by moc. Therefore, qobject_cast is actually a downcast operator,
similar to dynamic_cast.
In situations where you have base class pointers to derived class objects, downcasting
makes it possible to call derived class methods that do not exist in the base
class interface. In Example 15.1,we take advantage of the fact that QApplication,
and MyApplication, both derive from QObject.
E X A M P L E 1 5 . 1 src/qtrtti/myapp-classdef.cpp
[CODE]class MyApplication : public QApplication {
Q_OBJECT /* Required for Qt RTTI */
public:
static MyApplication* instance();
QString imagesURL() const;
[... other members ...]
};

MyApplication* MyApplication::instance() {
static MyApplication* inst = 0;
if (inst == 0) {
inst = qobject_cast<MyApplication*>(qApp);
}
return inst;
}
Because qApp always points to the currently running QApplication, this function
will return non-zero only if a MyApplication is the current running application.
The downcast operation, which some say is expensive, happens only once, to
ensure a properly typed MyApplication pointer. Future calls to instance()
will return the previously cast pointer, avoiding repeated calls to expensive runtime
checking operations. Now it becomes possible to obtain the properly typed
MyApplication instance from other locations in the code:



QString imagePath(QString filename) {
MyApplication* app = MyApplication::instance();
QString path = app->imagesURL() + "/" + filename;
return path;
}

wysota
19th March 2011, 14:58
The static part is obvious (at least for me), what is not obvious is why to create a singleton out of another singleton and why to do the check against zero.

Lykurg
20th March 2011, 11:37
why to create a singleton out of another singleton
To avoid the downcast operation, I guess.

and why to do the check against zero.
It because like you said. It should be save to call that function before a QApplication is constructed. (which is in most cases - in my opinion - too much safety coding...) This
MyApplication* MyApplication::instance() {
static MyApplication* inst = qobject_cast<MyApplication*>(qApp);
return inst;
}would produce e.g.
MyApplication::instance() // 0
QApplication a;
MyApplication::instance() // 0 instead of a valid pointer.

wysota
20th March 2011, 14:38
Unfortunately it doesn't protect you from this:

MyApplication *app = new MyApplication;
MyApplication::instance();
delete app;
if(MyApplication::instance()) MyApplication::instance()->whatever(); // segfault