PDA

View Full Version : Q_declare_private()



marf
19th July 2008, 19:17
I'm just looking at some example QT code, and I notice that someties in the header file there will be something like so:



class MyClassPrivate;

class MyClass : public QObject
{
public:
MyClass( QObject *parent = 0 );
...other non relevant stuff...
protected:
MyClassPrivate *const ptr;
MyClass( MyClassPrivate &the_ptr, QObject *parent = 0 );
private:
Q_DECLARE_PRIVATE( MyClass );
};


I'm just curious what does this "macro" do? Does it offer the ability to have a private version of the class? Why do they want a separate Protected Constructor? Can somebody give me an example why it is useful?

Thanks,

Michael

Holy Cheater
20th July 2008, 11:02
It expands to:


#define Q_DECLARE_PRIVATE(Class) \
inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr); } \
inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr); } \
friend class Class##Private;

It defines a d_func() which returns d_ptr (pointer to private class object).
It is used internally in QT, so it's not documented and you are not supposed to use this.

If you want to implement implicit sharing, look forward to QSharedData and QSharedDataPointer classes.

jpn
20th July 2008, 21:40
See also Qt Centre wiki: Private implementation.

marf
20th July 2008, 23:26
Thanks, I found that and it wasn't very useful.

However I stumbled upon this

http://techbase.kde.org/Policies/Library_Code_Policy#D-Pointers

and

http://techbase.kde.org/Policies/Library_Code_Policy/Shared_D-Pointer_Example

which bring alot of clarity to the issue.

However I have another question now.

In the second link above the example will basically never have private member variables in the 'KFooBase' but rather put them into the public: 'KFooBasePrivate' class.

also in this part of code


class KFooBasePrivate
{
public:
virtual ~KFooBasePrivate() { }
int someInteger;
};

why not do this


class KFooBase
{
public:
...the same as example...
private:
//Get rid of this stuff
//friend class KFooBasePrivate;
//inline KFooBasePrivate *d_func() { return d_ptr; }
//inline const KFooBasePrivate *d_func() const { return d_ptr; }
int someInteger;
};

I guess at the moment, I don't see the reason to go through all this trouble to make a "Private" class, to have member variables in there, when perhaps you could have just ignored this d_ptr stuff and used the private tag? Through lots of my reading today i read that it is best to use this method and not put private member variables in the private: part of a class, but they gave me no reason.

jpn
21st July 2008, 08:23
For libraries like Qt it is very important to retain binary compatibility so that existing applications keep working even if the library is updated. Just imagine the hassle if everyone had to recompile every single Qt application whenever the Qt library itself was updated. PIMPL makes it possible to introduce new functionality without breaking the ABI.

See also TT Knowledgebase: You frequently say that you cannot add this or that feature because it would break binary compatibility. What does this mean, really? (http://trolltech.com/developer/knowledgebase/362)

wysota
21st July 2008, 11:11
My wwWidgets use p-impl and Q_DECLARE_PRIVATE, so you can study the source to see what is does.

marf
21st July 2008, 19:09
jpn and wysota,

thanks for all your help so far. I have used your wwWidgets in combination with the KDE policy link I used above and I have made a test project. It doesn't want to set my integer for some reason, I commented the line that is crashing the program.

If one of you could be so kind to check out my little test program, that'd be great.

http://rapidshare.com/files/131457062/QtPimpl.tar.gz.html