The following basis in the last one, we enter the Qt source code to see Qt4.x is how Private Classes for.
As we said earlier, perhaps you will see many similar Q_D or Q_Q kind of macro. So, let's try to look at code like this:
void MyClass::setFoo( int i ) { Q_D(MyClass); d->m_foo = i; } int MyClass::foo() const { Q_D(const MyClass); return d->m_foo; }
According to the traditional C + + class, if we are to achieve such a getter and setter, we should use a private variable _i, then operation of this variable. In accordance with the Private Class on an approach that, we will build a MyClassPrivateData this class, and then use that data for all operations were commissioned.
Look at a more Qt example:
class MyObject: public QObject { Q_OBJECT public: MyObject(); virtual ~ MyObject(); void setMemberX( int x ); int memberX() const; void setMemberY( double y); double memberY() const; signals: void priorityChanged( MyObject::Priority priority ); private: int m_memberX; double m_memberY;
Qt implementation of the look:
class MyObjectPrivate; class MyObject: public QObject { Q_OBJECT public: MyObject(); virtual ~ MyObject(); void setMemberX( int x ); int memberX() const; void setMemberY( double y); double memberY() const; signals: void priorityChanged( MyObject::Priority priority ); protected: MyObjectPrivate * const d_ptr; private: Q_DECLARE_PRIVATE(MyObject); };
This example is very simple, one using traditional methods to achieve the other methods used Qt4.x. Qt4.x method is called D-Pointer, because it uses a pointer called d, as written above, that d_ptr. Using traditional methods, we need to write in private which all the private variables, usually it makes the entire file becomes very long, more importantly, users do not need this information. The method of using the D-Pointer, we become very beautiful interface: no longer that long string of private variables. You no longer need to publish your private variable to go out with them on the inside of your d pointer. If you want to modify the data type information, you do not need to modify the header files, you can simply change the category of private data.
One thing to note is that with a simple C + + class is different from the private class if you need to define signals and slots, this definition should be placed on the header file, rather than the one mentioned on the cpp file. This is because the qmake will detect. H file in the Q_OBJECT macro (which you must pay attention). Of course, you should not put such a private class on your head and file the same class, because doing so does not make sense. Common practice is to define a private header file, such as the use myclass_p.h naming (this is also the naming Qt). And remember, do not put private header files include the following you posted! Because this is not a part of your release, they are private. Then, in your myclass header files, use the
class MyClassPrivate;
This statement is not forward directly
#include "myclass_p.h"
In this way. This is to avoid the private header file, publish and declare before the compile time can be shortened.
In this class, private parts, we use a MyClassPrivate the const pointer d_ptr. If you need to subclass this class can use this guide should be on the protected part of this d_ptr, as the above code as. And, we also added the const keyword to ensure that it can only be initialized once.
Next, we met a wonderful macro: Q_DECLARE_PRIVATE. This is for? So, let's look at the start of this macro:
#define Q_DECLARE_PRIVATE(Class) \ inline Class##Private* d_func() { return reinterpret_cast(qGetPtrHelper(d_ptr)); } \ inline const Class##Private* d_func() const { return reinterpret_cast(qGetPtrHelper(d_ptr)); } \ friend class Class##Private;
If you look not know, then use our Q_DECLARE_PRIVATE (MyClass) start to see what followed it:
inline MyClassPrivate* d_func() { return reinterpret_cast(qGetPtrHelper(d_ptr)); } inline const MyClassPrivate* d_func() const { return reinterpret_cast(qGetPtrHelper(d_ptr)); } friend class MyClassPrivate;
It actually creates two inline of d_func () function, the return value are our d_ptr pointer and const pointer. In addition, it declared the MyClassPrivate class MyClass's friend. In this case, we can use in which the class MyClass Q_D (MyClass) and Q_D (const MyClass). Remember when we first saw that part of code? Now we take a look at this Q_D Dao Shi is and source!
// A template function for getting the instance to your private class instance. template static inline T *qGetPtrHelper(T *ptr) { return ptr; } // A macro for getting the d-pointer #define Q_D(Class) Class##Private * const d = d_func()
Or start following his look at the macro, it becomes
MyClassPrivate * const d = d_func()
In short, Qt for us to from d_func () to obtain MyClassPrivate pointer to package up the code, so that we can compare the use of object-oriented getter function to get the pointer.
Now that we have a rather clear that Qt is how to use D-Pointer to achieve what we have in front of the hidden information. However, there is a problem: If we concentrate MyClassPrivate most of the code inside, it may need to make implementation of the access to MyClass MyClassPrivate something. Now we get the main class through the D-Pointer access MyClassPrivate the data, but how in turn the main class to MyClassPrivate access data? Qt also provides the appropriate solution, that is Q_Q macro, for example:
class MyObjectPrivate { public: MyObjectPrivate(MyObject * parent): q_ptr( parent ), m_priority(MyObject::Low) {} void foo() { // Demonstrate how to make MyObject to emit a signal Q_Q(MyObject); emit q->priorityChanged( m_priority ); } // Members MyObject * const q_ptr; Q_DECLARE_PUBLIC(MyObject); MyObject::Priority m_priority; };
In the private class MyObjectPrivate in the main class through the constructor MyObject the pointer to q_ptr. Then we use a similar use of Q_DECLARE_PRIVATE main class as the other macro macro Q_DECLARE_PUBLIC. This macro does is make you able to Q_Q (Class) macro to use the main class pointer. And D-Pointer different, this time you need to use the Q_Pointer. The two are entirely relative, also will not repeat them here.
Now we have been able to use more ways to use Qt Private Classes realize information hidden. This is not just the realization of Qt, of course, you can not Q_D and Q_Q, but the use of their own way, these are irrelevant. Most importantly, we know a C + + class design ideas, this is the source code of Qt taught us.