[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    www/sites/developer/documentation/other
From:       Thiago Macieira <thiago () kde ! org>
Date:       2006-02-27 14:30:23
Message-ID: 1141050623.266574.21418.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 514114 by thiago:

Update the d-pointer-workaround example to Qt4 code.
Fix typo "itseld" -> "itself"


 M  +26 -23    binarycompatibility.html  


--- trunk/www/sites/developer/documentation/other/binarycompatibility.html #514113:514114
@@ -243,42 +243,35 @@
 can access the list of children with QObject::children(). However, a
 fancier and usually faster approach is to use a hashtable to store a
 mapping between your object and the extra data. For this purpose, Qt
-provides a pointer-based dictionary called QPtrDict.</p>
+provides a pointer-based dictionary called QHash (or QPtrDict in Qt3).</p>
 
 <p> The basic trick in your class implementation of class Foo is:</p>
 <ol>
 <li> Create a private data class FooPrivate.</li>
-<li> Create a static QPtrDict&lt;FooPrivate&gt;.
+<li> Create a static QHash&lt;Foo *, FooPrivate&gt;.
 
 <p> Note that some compilers/linkers (almost all, unfortunately) do
 not manage to create static objects in shared libraries. They simply
-forget to call the constructor. Therefore you need a static pointer to a
-QPtrDict, and an access function:</p>
+forget to call the constructor. Therefore you should use the 
+<tt>Q_GLOBAL_STATIC</tt> macro to create and access the object:</p>
 
 <table align="center"  width="80%"><tr><td BGCOLOR="#F0F0FF"><pre>
 	// BCI: Add a real d-pointer
-	static QPtrDict&lt;FooPrivate&gt;* d_ptr = 0;
-	static void cleanup_d_ptr()
-	{
-		delete d_ptr;
-	}
+	Q_GLOBAL_STATIC(QHash&lt;Foo *,FooPrivate&gt;>, d_func);
 	static FooPrivate* d( const Foo* foo )
 	{
-		if ( !d_ptr ) {
-			d_ptr = new QPtrDict&lt;FooPrivate&gt;
-			qAddPostRoutine( cleanup_d_ptr );
-		}
-		FooPrivate* ret = d_ptr->find( (void*) foo );
+		FooPrivate* ret = d_func()->value( foo, 0 );
 		if ( ! ret ) {
 			ret = new FooPrivate;
-			d_ptr->replace( (void*) foo, ret );
+			d_ptr->insert( foo, ret );
 		}
 		return ret;
 	}
 	static void delete_d( const Foo* foo )
 	{
-		if ( d_ptr )
-			d_ptr->remove( (void*) foo );
+		FooPrivate* ret = d_func()->value( foo, 0 );
+	        delete ret;
+	        d_func()->remove( foo );
 	}
 </pre></td></tr></table></li>
 
@@ -292,8 +285,7 @@
 <li> Add a line to your destructor:
 <table align="center"  width="80%"><tr><td BGCOLOR="#F0F0FF"><pre>
 	delete_d(this);
-</pre></td></tr></table>
-That's not really required, but saves some resources.</li>
+</pre></td></tr></table></li>
 
 <li> Do not forget to add a BCI remark, so that the hack can be
 removed in the next version of the library.</li>
@@ -314,10 +306,19 @@
 	}
 </pre></td></tr></table>
 then B::foo() is called directly. If class B inherits from class A which implements
-foo() and B itseld doesn't reimplement it, then C::foo() will in fact call A::foo().
+foo() and B itself doesn't reimplement it, then C::foo() will in fact call A::foo().
 If a newer version of the library adds B::foo(), C::foo() will call it only after
 a recompilation.</p>
 
+<p>Another more common example is:
+<table align="center"  width="80%"><tr><td BGCOLOR="#F0F0FF"><pre>
+	B b;		// B derives from A
+	b.foo();
+</pre></td></tr></table>
+then the call to foo() will not use the virtual table. That means that
+if B::foo() didn't exist in the library but now does, code that was
+compiled with the earlier version will still call A::foo().</p>
+
 <p>If you can't guarantee things will continue to work without a recompilation, move
 functionality from A::foo() to a new protected function A::foo2() and use this code:
 <table align="center"  width="80%"><tr><td BGCOLOR="#F0F0FF"><pre>
@@ -380,8 +381,8 @@
 
 <h3>Using signals instead of virtual functions</h3>
 <p>
-Qt's signals and slots are invoked using several virtual methods created by the Q_OBJECT macro
-and these virtual methods exist in every class inherited from QObject. Therefore adding new
+Qt's signals and slots are invoked using a special virtual method created by the Q_OBJECT macro
+and it exists in every class inherited from QObject. Therefore adding new
 signals and slots doesn't affect binary compatibility and the signals/slots mechanism can be
 used to emulate virtual functions.
 <table align="center"  width="80%"><tr><td BGCOLOR="#F0F0FF"><pre>
@@ -413,7 +414,7 @@
 	}
 </pre></td></tr></table>
 Function bar() will act like a virtual function, barslot() implements the actual functionality
-of it. Since signals and slots have void return value, data must be returned using arguments. As
+of it. Since signals have void return value, data must be returned using arguments. As
 there will be only one slot connected to the signal returning data from the slot this way will
 work without problems. Note that with Qt4 for this to work the connection type will have to be
 Qt::DirectConnection.</p>
@@ -445,6 +446,8 @@
 disconnect and then connect again, that will disconnect A::barslot() and connect B::barslot()
 instead.</p>
 
+<p>Note: the same can be accomplished by implementing a virtual slot.</p>
+
 <p align="right"> <small> <em>
 Matthias Ettrich <a href="mailto:ettrich@kde.org">ettrich@kde.org</a><br>
 Lubos Lunak <a href="mailto:l.lunak@kde.org">l.lunak@kde.org</a>
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic