diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-08 12:31:36 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-08 12:31:36 -0600 |
commit | d796c9dd933ab96ec83b9a634feedd5d32e1ba3f (patch) | |
tree | 6e3dcca4f77e20ec8966c666aac7c35bd4704053 /doc/object.doc | |
download | tqt3-d796c9dd933ab96ec83b9a634feedd5d32e1ba3f.tar.gz tqt3-d796c9dd933ab96ec83b9a634feedd5d32e1ba3f.zip |
Test conversion to TQt3 from Qt3 8c6fc1f8e35fd264dd01c582ca5e7549b32ab731
Diffstat (limited to 'doc/object.doc')
-rw-r--r-- | doc/object.doc | 763 |
1 files changed, 763 insertions, 0 deletions
diff --git a/doc/object.doc b/doc/object.doc new file mode 100644 index 000000000..9f03cdfae --- /dev/null +++ b/doc/object.doc @@ -0,0 +1,763 @@ +/**************************************************************************** +** +** Explanation of the Qt object model +** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the Qt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.QPL +** included in the packaging of this file. Licensees holding valid Qt +** Commercial licenses may use this file in accordance with the Qt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +/*! +\page object.html + +\title Qt Object Model + +The standard C++ Object Model provides very efficient runtime support +for the object paradigm. But the C++ Object Model's static nature is +inflexibile in certain problem domains. Graphical User Interface +programming is a domain that retquires both runtime efficiency and a +high level of flexibility. Qt provides this, by combining the speed of +C++ with the flexibility of the Qt Object Model. + +Qt adds these features to C++: + +\list +\i a very powerful mechanism for seamless object + communication called \link signalsandslots.html signals and + slots \endlink; +\i queryable and designable \link properties.html object + properties \endlink; +\i powerful \link eventsandfilters.html events and event filters \endlink, +\i contextual \link i18n.html string translation for internationalization \endlink; +\i sophisticated interval driven \link timers.html timers \endlink + that make it possible to elegantly integrate many tasks in an + event-driven GUI; +\i hierarchical and queryable \link objecttrees.html object + trees \endlink that organize object ownership in a natural way; +\i guarded pointers, \l QGuardedPtr, that are automatically + set to 0 when the referenced object is destroyed, unlike normal C++ + pointers which become "dangling pointers" when their objects are destroyed. +\endlist + +Many of these Qt features are implemented with standard C++ +techniques, based on inheritance from \l QObject. Others, like the +object communication mechanism and the dynamic property system, +retquire the \link metaobjects.html Meta Object System \endlink provided +by Qt's own \link moc.html Meta Object Compiler (moc) \endlink. + +The Meta Object System is a C++ extension that makes the language +better suited to true component GUI programming. Although templates can +be used to extend C++, the Meta Object System provides benefits using +standard C++ that cannot be achieved with templates; see \link +templates.html Why doesn't Qt use templates for signals and +slots? \endlink. + +*/ + + + + +/*! +\page timers.html + +\title Timers + +\l QObject, the base class of all Qt objects, provides the basic timer +support in Qt. With \l QObject::startTimer(), you start a timer with +an \e interval in milliseconds as argument. The function returns a +unique integer timer id. The timer will now "fire" every \e interval +milliseconds, until you explicitly call \l QObject::killTimer() with +the timer id. + +For this mechanism to work, the application must run in an event +loop. You start an event loop with \l QApplication::exec(). When a +timer fires, the application sends a QTimerEvent, and the flow of +control leaves the event loop until the timer event is processed. This +implies that a timer cannot fire while your application is busy doing +something else. In other words: the accuracy of timers depends on the +granularity of your application. + +There is practically no upper limit for the interval value (more than +one year is possible). The accuracy depends on the underlying operating +system. Windows 95/98 has 55 millisecond (18.2 times per second) +accuracy; other systems that we have tested (UNIX X11 and Windows NT) +can handle 1 millisecond intervals. + +The main API for the timer functionality is \l QTimer. That class +provides regular timers that emit a signal when the timer fires, and +inherits \l QObject so that it fits well into the ownership structure +of most GUI programs. The normal way of using it is like this: +\code + QTimer * counter = new QTimer( this ); + connect( counter, SIGNAL(timeout()), + this, SLOT(updateCaption()) ); + counter->start( 1000 ); +\endcode + +The counter timer is made into a child of this widget, so that when +this widget is deleted, the timer is deleted too. Next, its timeout +signal is connected to the slot that will do the work, and finally +it's started. + +QTimer also provides a simple one-shot timer API. \l QButton uses this +to show the button being pressed down and then (0.1 seconds later) be +released when the keyboard is used to "press" a button, for example: + +\code + QTimer::singleShot( 100, this, SLOT(animateTimeout()) ); +\endcode + +0.1 seconds after this line of code is executed, the same button's +animateTimeout() slot is called. + +Here is an outline of a slightly longer example that combines object +communication via signals and slots with a QTimer object. It +demonstrates how to use timers to perform intensive calculations in a +single-threaded application without blocking the user interface. + + \code + // The Mandelbrot class uses a QTimer to calculate the mandelbrot + // set one scanline at a time without blocking the CPU. It + // inherits QObject to use signals and slots. Calling start() + // starts the calculation. The done() signal is emitted when it + // has finished. Note that this example is not complete, just an + // outline. + + class Mandelbrot : public QObject + { + Q_OBJECT // retquired for signals/slots + public: + Mandelbrot( QObject *parent=0, const char *name ); + ... + public slots: + void start(); + signals: + void done(); + private slots: + void calculate(); + private: + QTimer timer; + ... + }; + + // + // Constructs and initializes a Mandelbrot object. + // + + Mandelbrot::Mandelbrot( QObject *parent=0, const char *name ) + : QObject( parent, name ) + { + connect( &timer, SIGNAL(timeout()), SLOT(calculate()) ); + ... + } + + // + // Starts the calculation task. The internal calculate() slot + // will be activated every 10 milliseconds. + // + + void Mandelbrot::start() + { + if ( !timer.isActive() ) // not already running + timer.start( 10 ); // timeout every 10 ms + } + + // + // Calculates one scanline at a time. + // Emits the done() signal when finished. + // + + void Mandelbrot::calculate() + { + ... // perform the calculation for a scanline + if ( finished ) { // no more scanlines + timer.stop(); + emit done(); + } + } + \endcode + + +*/ + + +/*! +\page properties.html + +\title Properties + +Qt provides a sophisticated property system similar to those supplied +by some compiler vendors. However, as a compiler- and +platform-independent library, Qt cannot rely on non-standard compiler +features like \c __property or \c [property]. Our solution works with +\e any standard C++ compiler on every platform we support. It's based +on the meta-object system that also provides object communication +through \link signalsandslots.html signals and slots\endlink. + +The \c Q_PROPERTY macro in a class declaration declares a +property. Properties can only be declared in classes that inherit \l +QObject. A second macro, \c Q_OVERRIDE, can be used to override some +aspects of an inherited property in a subclass. (See \link #override +Q_OVERRIDE\endlink.) + +To the outer world, a property appears to be similar to a data member. +But properties have several features that distinguish them from +ordinary data members: + +\list +\i A read function. This always exists. + +\i A write function. This is optional: read-only properties like \l +QWidget::isDesktop() do not have one. + +\i An attribute "stored" that indicates persistence. Most properties +are stored, but a few virtual properties are not. For example, \l +QWidget::minimumWidth() isn't stored, since it's just a view of +\l QWidget::minimumSize(), and has no data of its own. + +\i A reset function to set a property back to its context specific +default value. This is very rare, but for example, \l QWidget::font() +needs this, since no call to \l QWidget::setFont() can mean 'reset to +the context specific font'. + +\i An attribute "designable" that indicates whether it makes sense to +make the property available in a GUI builder (e.g. \link +designer-manual.book Qt Designer\endlink). For most properties this +makes sense, but not for all, e.g. \l QButton::isDown(). The user can +press buttons, and the application programmer can make the program +press its own buttons, but a GUI design tool can't press buttons. + +\endlist + +The read, write, and reset functions must be public member functions +from the class in which the property is defined. + +Properties can be read and written through generic functions in +QObject without knowing anything about the class in use. These two +function calls are equivalent: + +\code + // QButton *b and QObject *o point to the same button + b->setDown( TRUE ); + o->setProperty( "down", TRUE ); +\endcode + +Equivalent, that is, except that the first is faster, and provides +much better diagnostics at compile time. When practical, the first is +better. However, since you can get a list of all available properties +for any QObject through its \l QMetaObject, \l QObject::setProperty() +can give you control over classes that weren't available at compile +time. + +As well as QObject::setProperty(), there is a corresponding \l +QObject::property() function. \l QMetaObject::propertyNames() returns +the names of all available properties. \l QMetaObject::property() +returns the property data for a named property: a \l QMetaProperty +object. + +Here's a simple example that shows the most important property +functions in use: + +\code + class MyClass : public QObject + { + Q_OBJECT + public: + MyClass( QObject * parent=0, const char * name=0 ); + ~MyClass(); + + enum Priority { High, Low, VeryHigh, VeryLow }; + void setPriority( Priority ); + Priority priority() const; + }; +\endcode + +The class has a property "priority" that is not yet known to the meta +object system. In order to make the property known, you must +declare it with the \c Q_PROPERTY macro. The syntax is as follows: + +\code +Q_PROPERTY( type name READ getFunction [WRITE setFunction] + [RESET resetFunction] [DESIGNABLE bool] + [SCRIPTABLE bool] [STORED bool] ) +\endcode + +For the declaration to be valid, the get function must be const and +to return either the type itself, a pointer to it, or a reference to +it. The optional write function must return void and must take exactly +one argument, either the type itself, a pointer or a const reference +to it. The meta object compiler enforces this. + +The type of a property can be any \l QVariant supported type or an +enumeration type declared in the class itself. Since \c MyClass uses +the enumeration type \c Priority for the property, this type must be +registered with the property system as well. + +There are two exceptions to the above: The type of a property can also +be either \link QValueList QValueList\<QVariant\>\endlink or \link +QMap QMap\<QString,QVariant\>\endlink. In +these cases the type must be specified as \c QValueList or as \c QMap +(i.e. without their template parameters). + +It is possible to set a value by name, like this: +\code + obj->setProperty( "priority", "VeryHigh" ); +\endcode +In the case of \c QValueList and \c QMap properties the value passes +is a QVariant whose value is the entire list or map. + +Enumeration types are registered with the \c Q_ENUMS macro. Here's the +final class declaration including the property related declarations: + +\code + class MyClass : public QObject + { + Q_OBJECT + Q_PROPERTY( Priority priority READ priority WRITE setPriority ) + Q_ENUMS( Priority ) + public: + MyClass( QObject * parent=0, const char * name=0 ); + ~MyClass(); + + enum Priority { High, Low, VeryHigh, VeryLow }; + void setPriority( Priority ); + Priority priority() const; + }; +\endcode + +Another similar macro is \c Q_SETS. Like \c Q_ENUMS, it registers an +enumeration type but marks it in addition as a "set", i.e. the +enumeration values can be OR-ed together. An I/O class might have +enumeration values "Read" and "Write" and accept "Read|Write": such an +enum is best handled with \c Q_SETS, rather than \c Q_ENUMS. + +The remaining keywords in the \c Q_PROPERTY section are \c RESET, \c +DESIGNABLE, \c SCRIPTABLE and \c STORED. + +\c RESET names a function that will set the property to its default +state (which may have changed since initialization). The function +must return void and take no arguments. + +\c DESIGNABLE declares whether this property is suitable for +modification by a GUI design tool. The default is \c TRUE for +writable properties; otherwise \c FALSE. Instead of \c TRUE or \c +FALSE, you can specify a boolean member function. + +\c SCRIPTABLE declares whether this property is suited for access by a +scripting engine. The default is \c TRUE. Instead of \c TRUE or \c FALSE, +you can specify a boolean member function. + +\c STORED declares whether the property's value must be remembered +when storing an object's state. Stored makes only sense for writable +properties. The default value is \c TRUE. Technically superfluous +properties (like QPoint pos if QRect geometry is already a property) +define this to be \c FALSE. + + +Connected to the property system is an additional macro, "Q_CLASSINFO", +that can be used to attach additional name/value-pairs to a class' +meta object, for example: + +\code + Q_CLASSINFO( "Version", "3.0.0" ) +\endcode + +Like other meta data, class information is accessible at runtime +through the meta object, see \l QMetaObject::classInfo() for details. + +\target override +\section1 Q_OVERRIDE + +When you inherit a QObject subclass you may wish to override some +aspects of some of the class's properties. + +For example, in QWidget we have the autoMask property defined like +this: +\code + Q_PROPERTY( bool autoMask READ autoMask WRITE setAutoMask DESIGNABLE false SCRIPTABLE false ) +\endcode + +But we need to make the auto mask property designable in some QWidget +subclasses. Similarly some classes will need this property to be +scriptable (e.g. for QSA). This is achieved by overriding these +features of the property in a subclass. In QCheckBox, for example, we +achieve this using the following code: +\code + Q_OVERRIDE( bool autoMask DESIGNABLE true SCRIPTABLE true ) +\endcode + +Another example is QToolButton. By default QToolButton has a read-only +"toggleButton" property, because that's what it inherits from QButton: +\code + Q_PROPERTY( bool toggleButton READ isToggleButton ) +\endcode + +But we want to make our tool buttons able to be toggled, so we write a +WRITE function in QToolButton, and use the following property override +to make it acessible: +\code + Q_OVERRIDE( bool toggleButton WRITE setToggleButton ) +\endcode +The result is read-write (and scriptable and designable, since we now +have a WRITE function) boolean property "toggleButton" for tool +buttons. + +*/ + +/*! +\page eventsandfilters.html + +\title Events and Event Filters + +In Qt, an event is an object that inherits \l QEvent. Events are +delivered to objects that inherit \l QObject through calling \l +QObject::event(). Event delivery means that an event has occurred, the +QEvent indicates precisely what, and the QObject needs to respond. Most +events are specific to \l QWidget and its subclasses, but there are +important events that aren't related to graphics, for example, socket +activation, which is the event used by \l QSocketNotifier for its +work. + +Some events come from the window system, e.g. \l QMouseEvent, some +from other sources, e.g. \l QTimerEvent, and some come from the +application program. Qt is symmetric, as usual, so you can send +events in exactly the same ways as Qt's own event loop does. + +Most events types have special classes, most commonly \l QResizeEvent, +\l QPaintEvent, \l QMouseEvent, \l QKeyEvent and \l QCloseEvent. +There are many others, perhaps forty or so, but most are rather odd. + +Each class subclasses QEvent and adds event-specific functions; see, +for example, \l QResizeEvent. In the case of QResizeEvent, \l +QResizeEvent::size() and \l QResizeEvent::oldSize() are added. + +Some classes support more than one event type. \l QMouseEvent +supports mouse moves, presses, shift-presses, drags, clicks, +right-presses, etc. + +Since programs need to react in varied and complex ways, Qt's +event delivery mechanisms are flexible. The documentation for +\l QApplication::notify() concisely tells the whole story, here we +will explain enough for 99% of applications. + +The normal way for an event to be delivered is by calling a virtual +function. For example, \l QPaintEvent is delivered by calling \l +QWidget::paintEvent(). This virtual function is responsible for +reacting appropriately, normally by repainting the widget. If you +do not perform all the necessary work in your implementation of the +virtual function, you may need to call the base class's +implementation; for example: +\code + MyTable::contentsMouseMoveEvent( QMouseEvent *me ) + { + // my implementation + + QTable::contentsMouseMoveEvent( me ); // hand it on + } +\endcode +If you want to replace the base class's function then you must +implement everything yourself; but if you only want to extend the base +class's functionality, then you implement what you want and then call +the base class. + +Occasionally there isn't such an event-specific function, or the +event-specific function isn't sufficient. The most common example is +tab key presses. Normally, those are interpreted by QWidget to move +the keyboard focus, but a few widgets need the tab key for themselves. + +These objects can reimplement \l QObject::event(), the general event +handler, and either do their event handling before or after the usual +handling, or replace it completely. A very unusual widget that both +interprets tab and has an application-specific custom event might +contain: + +\code + bool MyClass:event( QEvent *evt ) { + if ( evt->type() == QEvent::KeyPress ) { + QKeyEvent *ke = (QKeyEvent *)evt; + if ( ke->key() == Key_Tab ) { + // special tab handling here + ke->accept(); + return TRUE; + } + } else if ( evt->type() >= QEvent::User ) { + QCustomEvent *ce = (QCustomEvent*) evt; + // custom event handling here + return TRUE; + } + return QWidget::event( evt ); + } +\endcode + +More commonly, an object needs to look at another's events. Qt +supports this using \l QObject::installEventFilter() (and the +corresponding remove). For example, dialogs commonly want to filter +key presses for some widgets, e.g. to modify Return-key handling. + +An event filter gets to process events before the target object does. +The filter's \l QObject::eventFilter() implementation is called, and +can accept or reject the filter, and allow or deny further processing +of the event. If all the event filters allow further processing of an +event, the event is sent to the target object itself. If one of them +stops processing, the target and any later event filters don't get to +see the event at all. + +It's also possible to filter \e all events for the entire application, +by installing an event filter on \l QApplication. This is what \l +QToolTip does in order to see \e all the mouse and keyboard activity. +This is very powerful, but it also slows down event delivery of every +single event in the entire application, so it's best avoided. + +The global event filters are called before the object-specific +filters. + +Finally, many applications want to create and send their own events. + +Creating an event of a built-in type is very simple: create an object +of the relevant type, and then call \l QApplication::sendEvent() or \l +QApplication::postEvent(). + +sendEvent() processes the event immediately - when sendEvent() +returns, (the event filters and) the object have already processed the +event. For many event classes there is a function called isAccepted() +that tells you whether the event was accepted or rejected by the last +handler that was called. + +postEvent() posts the event on a queue for later dispatch. The next +time Qt's main event loop runs, it dispatches all posted events, with +some optimization. For example, if there are several resize events, +they are are compacted into one. The same applies to paint events: \l +QWidget::update() calls postEvent(), which minimizes flickering and +increases speed by avoiding multiple repaints. + +postEvent() is also often used during object initialization, since the +posted event will typically be dispatched very soon after the +initialization of the object is complete. + +To create events of a custom type, you need to define an event number, +which must be greater than \c QEvent::User, and probably you also need +to subclass \l QCustomEvent in order to pass characteristics about +your custom event. See the documentation to \l QCustomEvent for +details. + +*/ + + +/*! +\page objecttrees.html + +\title Object Trees and Object Ownership + +\link QObject QObjects\endlink organize themselves in object trees. +When you create a QObject with another object as parent, it's added to +the parent's \link QObject::children() children() \endlink list, and +is deleted when the parent is. It turns out that this approach fits +the needs of GUI objects very well. For example, a \l QAccel (keyboard +accelerator) is a child of the relevant window, so when the user closes +that window, the accelerator is deleted too. + +The static function \l QObject::objectTrees() provides access to all +the root objects that currently exist. + +\l QWidget, the base class of everything that appears on the screen, +extends the parent-child relationship. A child normally also becomes a +child widget, i.e. it is displayed in its parent's coordinate system +and is graphically clipped by its parent's boundaries. For example, +when the an application deletes a message box after it has been +closed, the message box's buttons and label are also deleted, just as +we'd want, because the buttons and label are children of the message +box. + +You can also delete child objects yourself, and they will remove +themselves from their parents. For example, when the user removes a +toolbar it may lead to the application deleting one of its \l QToolBar +objects, in which case the tool bar's \l QMainWindow parent would +detect the change and reconfigure its screen space accordingly. + +The debugging functions \l QObject::dumpObjectTree() and \l +QObject::dumpObjectInfo() are often useful when an application looks or +acts strangely. + +*/ + + +/*! +\page templates.html + +\title Why doesn't Qt use templates for signals and slots? + +A simple answer is that when Qt was designed, it was not possible to +fully exploit the template mechanism in multi-platform applications due +to the inadequacies of various compilers. Even today, many widely used +C++ compilers have problems with advanced templates. For example, you +cannot safely rely on partial template instantiation, which is essential +for some non-trivial problem domains. Thus Qt's usage of templates has +to be rather conservative. Keep in mind that Qt is a multi-platform +toolkit, and progress on the Linux/g++ platform does not necessarily +improve the situation elsewhere. + +Eventually those compilers with weak template implementations will +improve. But even if all our users had access to a fully standards +compliant modern C++ compiler with excellent template support, we would +not abandon the string-based approach used by our meta object compiler. +Here are five reasons why: + +<h3>1. Syntax matters</h3> + +Syntax isn't just sugar: the syntax we use to express our algorithms can +significantly affect the readability and maintainability of our code. +The syntax used for Qt's signals and slots has proved very successful in +practice. The syntax is intuitive, simple to use and easy to read. +People learning Qt find the syntax helps them understand and utilize the +signals and slots concept -- despite its highly abstract and generic +nature. Furthermore, declaring signals in class definitions ensures that +the signals are protected in the sense of protected C++ member +functions. This helps programmers get their design right from the very +beginning, without even having to think about design patterns. + +<h3>2. Precompilers are good</h3> + +Qt's <tt>moc</tt> (Meta Object Compiler) provides a clean way to go +beyond the compiled language's facilities. It does so by generating +additional C++ code which can be compiled by any standard C++ compiler. +The <tt>moc</tt> reads C++ source files. If it finds one or more class +declarations that contain the "Q_OBJECT" macro, it produces another C++ +source file which contains the meta object code for those classes. The +C++ source file generated by the <tt>moc</tt> must be compiled and +linked with the implementation of the class (or it can be +<tt>#included</tt> into the class's source file). Typically <tt>moc</tt> +is not called manually, but automatically by the build system, so it +retquires no additional effort by the programmer. + +There are other precompilers, for example, <tt>rpc</tt> and +<tt>idl</tt>, that enable programs or objects to communicate over +process or machine boundaries. The alternatives to precompilers are +hacked compilers, proprietary languages or graphical programming tools +with dialogs or wizards that generate obscure code. Rather than locking +our customers into a proprietary C++ compiler or into a particular +Integrated Development Environment, we enable them to use whatever tools +they prefer. Instead of forcing programmers to add generated code into +source repositories, we encourage them to add our tools to their build +system: cleaner, safer and more in the spirit of UNIX. + + +<h3>3. Flexibility is king</h3> + +C++ is a standarized, powerful and elaborate general-purpose language. +It's the only language that is exploited on such a wide range of +software projects, spanning every kind of application from entire +operating systems, database servers and high end graphics +applications to common desktop applications. One of the keys to C++'s +success is its scalable language design that focuses on maximum +performance and minimal memory consumption whilst still maintaining +ANSI-C compatibility. + +For all these advantages, there are some downsides. For C++, the static +object model is a clear disadvantage over the dynamic messaging approach +of Objective C when it comes to component-based graphical user interface +programming. What's good for a high end database server or an operating +system isn't necessarily the right design choice for a GUI frontend. +With <tt>moc</tt>, we have turned this disadvantage into an advantage, +and added the flexibility retquired to meet the challenge of safe and +efficient graphical user interface programming. + +Our approach goes far beyond anything you can do with templates. For +example, we can have object properties. And we can have overloaded +signals and slots, which feels natural when programming in a language +where overloads are a key concept. Our signals add zero bytes to the +size of a class instance, which means we can add new signals without +breaking binary compatibility. Because we do not rely on excessive +inlining as done with templates, we can keep the code size smaller. +Adding new connections just expands to a simple function call rather +than a complex template function. + +Another benefit is that we can explore an object's signals and slots at +runtime. We can establish connections using type-safe call-by-name, +without having to know the exact types of the objects we are connecting. +This is impossible with a template based solution. This kind of runtime +introspection opens up new possibilities, for example GUIs that are +generated and connected from Qt Designer's XML <tt>ui</tt> files. + +<h3>4. Calling performance is not everything</h3> + +Qt's signals and slots implementation is not as fast as a template-based +solution. While emitting a signal is approximately the cost of four +ordinary function calls with common template implementations, Qt +retquires effort comparable to about ten function calls. This is not +surprising since the Qt mechanism includes a generic marshaller, +introspection and ultimately scriptability. It does not rely on +excessive inlining and code expansion and it provides unmatched runtime +safety. Qt's iterators are safe while those of faster template-based +systems are not. Even during the process of emitting a signal to several +receivers, those receivers can be deleted safely without your program +crashing. Without this safety, your application would eventually crash +with a difficult to debug free'd memory read or write error. + +Nonetheless, couldn't a template-based solution improve the performance +of an application using signals and slots? While it is true that Qt adds +a small overhead to the cost of calling a slot through a signal, the +cost of the call is only a small proportion of the entire cost of a +slot. Benchmarking against Qt's signals and slots system is typically +done with empty slots. As soon as you do anything useful in your slots, +for example a few simple string operations, the calling overhead becomes +negligible. Qt's system is so optimized that anything that retquires +operator new or delete (for example, string operations or +inserting/removing something from a template container) is significantly +more expensive than emitting a signal. + +Aside: If you have a signals and slots connection in a tight inner loop +of a performance critical task and you identify this connection as the +bottleneck, think about using the standard listener-interface pattern +rather than signals and slots. In cases where this occurs, you probably +only retquire a 1:1 connection anyway. For example, if you have an object +that downloads data from the network, it's a perfectly sensible design +to use a signal to indicate that the requested data arrived. But if you +need to send out every single byte one by one to a consumer, use a +listener interface rather than signals and slots. + +<h3>5. No limits</h3> + +Because we had the <tt>moc</tt> for signals and slots, we could add +other useful things to it that could not not be done with templates. +Among these are scoped translations via a generated <tt>tr()</tt> +function, and an advanced property system with introspection and +extended runtime type information. The property system alone is a great +advantage: a powerful and generic user interface design tool like Qt +Designer would be a lot harder to write - if not impossible - without a +powerful and introspective property system. + +C++ with the <tt>moc</tt> preprocessor essentially gives us the +flexibility of Objective-C or of a Java Runtime Environment, while +maintaining C++'s unique performance and scalability advantages. It is +what makes Qt the flexible and comfortable tool we have today. + +*/ |