PDA

View Full Version : PIMPL, what do I miss?



Lykurg
25th February 2011, 14:26
Hi,

lately I make myself familiar with the PIMPL idiom. And all examples do in the private declaration something like this:
#define PIMPL_DECLARE_PRIVATE(Class) \
private: \
inline Class##Private* d_func() {return reinterpret_cast<Class##Private*>(dPtr);} \
inline const Class##Private* d_func() const {return reinterpret_cast<const Class##Private*>(dPtr);} \
void* dPtr;
And assuming that you only work with normal classes: Why they all use reinterpret_cast? I don't see the need even if reinterpret_cast is cheap. What's wrong with:

#define PIMPL_DECLARE_PRIVATE(Class) \
private: \
inline Class##Private* d_func() {return dPtr;} \
inline const Class##Private* d_func() const {return const_cast<const Class##Private*>(dPtr);} \
Class##Private* dPtr;
Do I miss something important here?

franz
25th February 2011, 14:33
I'm not exactly sure what the purpose is. In pimpling, I usually don't use the macros and just take the following approach:

class MyClassPrivate;

class MyClass
{
// ...
private:
MyClassPrivate *d;
};


This suits me fine and as far as I can see has the same effect as using the above macros.

high_flyer
25th February 2011, 14:44
My guess is that its because reinterpret_cast guarantees the original type when you cast back.

wysota
25th February 2011, 15:08
I think a simple "return dPtr" would not work as "void*" and "WhatEverPrivate*" are not type-compatible. It might have worked in C but not C++. Same goes for the second cast -- there is no implicit cast between void* and other pointer types. I guess reinterpret_cast might be replaced by static_cast as well. These are just guesses though, I never understood the differences between some cast types (especially reinterpret_cast).

Lykurg
25th February 2011, 15:29
I think a simple "return dPtr" would not work as "void*" and "WhatEverPrivate*" are not type-compatible. It might have worked in C but not C++.
Yes, but therefore I would change the private pointer from void* to WhatEverPrivate* (dPtr in my case). So what I see "they" need the cast because the declare a void pointer. But if you declare direct a WhatEverPrivate pointer there is no need to cast. (only the const of course.)

@high_flyer That should only be a problem when you use dynamic_cast, because it can return a NULL pointer. But I am not sure...

@franz I want to use templates to be flexible and to add more stuff later if needed. And it not just one class.

wysota
25th February 2011, 15:43
Maybe my initial response (which I deleted and instead wrote what I have written) would be closer to truth. The reinterpret_cast might serve as a trick to have a pimpl class that does not inherit from the pimpl class of the base class of the public class.

class APrivate {};
class A {
private:
APrivate *d;
};

class BPrivate {}; // doesn't inherit APrivate

class B : public A {
private:
BPrivate *d;
};

high_flyer
25th February 2011, 15:50
a pimpl class that does not inherit from the pimpl class of the base class of the public class.
LOL.
I had to read it several times to get it!

nish
28th February 2011, 09:59
a little off-topic question but here it goes.

PIMPL says that your main class should only contain public functions and only a single private d pointer.

But how you guys handle the case when i need some *private* slots in my main class. As moc only reads .h files ( it can parse .cpp as well but i dont want that)
i need to have the private slots in my main class as well.. this makes my class a little bit more subject to change.

Qt sources solves this by declaring the private class in "*_p.h" files. But then they put a BIG warning on those private headers. But developers as we know
push the limits and include the private headers for some real hack ( there is a example of this in QtCentre Wiki as well !! )

Anyone done this differently?