You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
9.7 KiB
170 lines
9.7 KiB
14 years ago
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||
|
<!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/doc/object.doc:610 -->
|
||
|
<html>
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||
|
<title>Why doesn't Qt use templates for signals and slots?</title>
|
||
|
<style type="text/css"><!--
|
||
|
fn { margin-left: 1cm; text-indent: -1cm; }
|
||
|
a:link { color: #004faf; text-decoration: none }
|
||
|
a:visited { color: #672967; text-decoration: none }
|
||
|
body { background: #ffffff; color: black; }
|
||
|
--></style>
|
||
|
</head>
|
||
|
<body>
|
||
|
|
||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||
|
<tr bgcolor="#E5E5E5">
|
||
|
<td valign=center>
|
||
|
<a href="index.html">
|
||
|
<font color="#004faf">Home</font></a>
|
||
|
| <a href="classes.html">
|
||
|
<font color="#004faf">All Classes</font></a>
|
||
|
| <a href="mainclasses.html">
|
||
|
<font color="#004faf">Main Classes</font></a>
|
||
|
| <a href="annotated.html">
|
||
|
<font color="#004faf">Annotated</font></a>
|
||
|
| <a href="groups.html">
|
||
|
<font color="#004faf">Grouped Classes</font></a>
|
||
|
| <a href="functions.html">
|
||
|
<font color="#004faf">Functions</font></a>
|
||
|
</td>
|
||
|
<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>Why doesn't Qt use templates for signals and slots?</h1>
|
||
|
|
||
|
|
||
|
|
||
|
<p> 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.
|
||
|
<p> 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 <a href="metaobjects.html#meta-object">meta object</a> compiler.
|
||
|
Here are five reasons why:
|
||
|
<p> <h3>1. Syntax matters</h3>
|
||
|
<p> 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.
|
||
|
<p> <h3>2. Precompilers are good</h3>
|
||
|
<p> Qt's <tt><a href="moc.html#moc">moc</a></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
|
||
|
requires no additional effort by the programmer.
|
||
|
<p> 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.
|
||
|
<p> <h3>3. Flexibility is king</h3>
|
||
|
<p> 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.
|
||
|
<p> 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 required to meet the challenge of safe and
|
||
|
efficient graphical user interface programming.
|
||
|
<p> 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.
|
||
|
<p> 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.
|
||
|
<p> <h3>4. Calling performance is not everything</h3>
|
||
|
<p> 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
|
||
|
requires 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.
|
||
|
<p> 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 requires
|
||
|
operator new or delete (for example, string operations or
|
||
|
inserting/removing something from a template container) is significantly
|
||
|
more expensive than emitting a signal.
|
||
|
<p> 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 require 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.
|
||
|
<p> <h3>5. No limits</h3>
|
||
|
<p> 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.
|
||
|
<p> 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.
|
||
|
<p>
|
||
|
<!-- eof -->
|
||
|
<p><address><hr><div align=center>
|
||
|
<table width=100% cellspacing=0 border=0><tr>
|
||
|
<td>Copyright © 2007
|
||
|
<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
|
||
|
<td align=right><div align=right>Qt 3.3.8</div>
|
||
|
</table></div></address></body>
|
||
|
</html>
|