Data hiding QT d pointer detail

Source: Internet
Author: User

Recently see the code useful to QT in the Q_d pointer, went to learn the next, found really useful, so write an article summarized under.

Student.h
class cstudent
{public
:
	cstudent ();
	~cstudent ();
Private:
	string m_name;
	int    m_age;
	int    m_grade;
};
If our class belongs to a dynamic library, then providing a DLL to the outside exposes the data structure of my class, the user will know that the original name is a string type, the age is an int type, and so on, which I do not want to see, nor does it conform to my original intention of setting it to private.
How can we solve the problem above? Maybe we can do this:

Student.h
class cstudentdate;
Class Cstudent
{public
:
	cstudent ();
	~cstudent ();
Private:
	cstudentdate* d_ptr;
};

Student.cpp
class cstudentdate
{public
:
	string m_name;
	int    m_age;
	int    m_grade;
};

We put all of the cstudent data into his data management class and put all of its data management classes into its CPP, so that even if you like to provide your DLL and. h files, your members ' data types will not be exposed. This is a way to hide data. The advantage is that it hides the data we don't want to reveal, and we don't affect the size of the Cstudent class even if we add a data item, such as adding a class member. Binary compatibility can be achieved.

Well, we're back to the D-pointer above, and the other D-pointers are a way for QT to implement information hiding. Its specific implementation principle and the above, we return to the previous D pointer up, the other D pointer is QT in order to achieve information hiding a way. Its concrete implementation principle is the same as above cstudent, equivalent to our d_ptr pointer. is equivalent to the d_ptr pointer in our Cstudent class. Let's take a look at how Qt's D pointer is implemented.
The following are from: http://blog.csdn.net/rabinsong/article/details/9474859



As shown above, this is the general form of the pointer to the QT root node, below to see the general form of the non-root node,

Note here that Qwidge derives from Qobject, which does not have d_ptr, but its member functions can access d_ptr because D_ptr is a protected member, and its object model contains D_PTR (this is because derived classes inherit all members of the parent class).


Let's look at how QT is implemented for both of these scenarios:

Qobject.h file:
  
qobjectdata {public  
:  
    qobject *q_ptr;  
    ...  
};  
  
Class Q_core_export Qobject  
{  
    ...  
    Q_declare_private (qobject) public  
:  
    q_invokable explicit Qobject (Qobject *parent=0);  
    Virtual ~qobject ();  
    ...  
  
Protected:  
    qobject (qobjectprivate &dd, Qobject *parent = 0);  
    ...      
      
Protected:  
    qscopedpointer<qobjectdata> d_ptr;  
    ...  
};  
As above, here I counted the other items, only kept the d_ptr related items, first of all to see what Q_declare_private (Qobject) is:
    Inline class# #Private * D_func () {return reinterpret_cast<class# #Private *> (Qgetptrhelper (D_ptr));} \  
    inline Const class# #Private * D_FUNC () const {return reinterpret_cast<const class# #Private *> (Qgetptrhelper (d_ptr )); } \  
    friend class class# #Private;  
According to the macro definition, q_declare_private (qobject) translates as follows:
Inline Qobjectprivate *d_func ()
{
Return reinterpret_cast<qobjectprivate *> (Qgetptrhelper (d_ptr));
}
Inline const qobjectprivate *d_func () const
{
return reinterpret_cast<const qobjectprivate *> (Qgetptrhelper (d_ptr));
}
Friend class Qobjectprivate;

Then look at the definition of Qgetptrhelper:

Template <typename t> static inline T *qgetptrhelper (t *ptr)  
{   
    return ptr;  
}  
Look at Qscopepointer, it is similar to the smart pointer, so do not care about the release of D_ptr, when leaving the scope of Qscopepointer, Qscopepointer will automatically release D_ptr point to the heap memory, then when this pointer is generated? When was the q_ptr assigned to the value? Let's take a look at the implementation of Qobject.cpp:
Qobject::qobject (Qobject *parent)  
    : d_ptr (new Qobjectprivate)  
{  
    q_d (qobject);  
    D_ptr->q_ptr = this;  
    ...  
}  
  
Qobject::qobject (qobjectprivate &dd, Qobject *parent)  
    : D_ptr (&DD)  
{  
    q_d (qobject);  
    D_ptr->q_ptr = this;  
    ...  
}  
We look at the first constructor, the d_ptr of the root node points to new qobjectprivate, and qobjectprivate derives from Qobjectdata, so what does the Q_d (QOBJECT) macro mean?
#define Q_D (Class) class# #Private * Const D = D_func ()  
q_d (qobject);
  
It is not difficult to see Q_d (Qobject); Defines a Qobjectprivate constant pointer to the return value of D_func (), which is d_ptr (see header file D_func () definition), so we can access the D pointer with the Q_D macro.
For the second constructor, let's take a look at the implementation of the non-root node d_ptr:
Header file:

Class Q_core_export Qobjectprivate:public qobjectdata  
{  
    q_declare_public (qobject)  
    ...  
};  
  
Class Q_gui_export Qwidgetprivate:public qobjectprivate  
{  
    q_declare_public (qwidget)  
    ...  
};  
  
Class Q_gui_export Qwidget:public qobject  
{  
    ...  
    Q_declare_private (qwidget) ...  
Public: ...  
    Explicit Qwidget (qwidget* parent = 0, qt::windowflags f = 0);  
    ...  
};  
Let's look at Q_declare_public macro first:
#define Q_DECLARE_PUBLIC (Class)                                    \  
    inline class* q_func () {return static_cast<class *> (q_ptr);} \  
    Inline const class* Q_func () const {return Static_cast<const class *> (q_ptr);} \  
    friend class class;  
According to the macro definition, q_declare_public (qobject) translates as follows:
  
inline Qobject *q_func ()  
{   
    return static_cast<qobject *> (q_ PTR);  
}   
Inline const Qobject *q_func () const   
{   
    return static_cast<const qobject *> (q_ptr);  
}   
Friend class Qobject;  
Q_declare_public (Qwidget) translates as follows:
  
inline Qwidget *q_func ()  
{   
    return static_cast<qwidget *> (q_ptr );  
}   
Inline const Qwidget *q_func () const   
{   
    return static_cast<const qwidget *> (q_ptr);  
}   
Friend class Qwidget;  
Note that the q_ptr here are publicly declared in Qobjectdata, and qobjectprivate,qwidgetprivate are derived or indirectly derived from Qobjectdata, so you can access q_ptr.
Next look at the translation of Q_declare_private (Qwidget):
Inline qwidgetprivate *d_func ()  
{  
    return reinterpret_cast<qwidgetprivate *> (Qgetptrhelper (d_ptr));   
}  
Inline const qwidgetprivate *d_func () const  
{   
    return reinterpret_cast<const qwidgetprivate *> (Qgetptrhelper (d_ptr));  
}  
Friend class Qwidgetprivate;
Next look at the implementation of the Qwidget constructor:
Qwidget::qwidget (Qwidget *parent, Qt::windowflags f)  
    : Qobject (*new qwidgetprivate, 0)  
{  
    ...  
See Qobject (*new qwidgetprivate, 0) here called the second constructor of Qobject, which points d_ptr to the heap memory pointed to by new qwidgetprivate.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.