Home » Community » Forums » » The C++ Pimpl
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 The C++ Pimpl
Post Reply 
I thought at first that it must have been a new skin condition that teenagers get

As for the _ in variable names; YUCK!

Otherwise it was an excellent article, concise and to the point. Well explained.


 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

to not pollute the global namespace, you could use an anonymouse namespace

 User Rating: 1043   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Don't take this the wrong way, but if there is already an article about it at www.gotw.ca, what does your one add?

Also, you don't explain what the advantage of using pimpl is.

 User Rating: 1015    Report this Post to a Moderator | Link

If the goal you're setting up is the only one, I'd rather use an interface.

E.g.

typedef struct interface;

...

interface IPublicClass
{
virtual void SomeFunc() = 0; // pure virtual
};

...

class PrivateClass : public IPublicClass
{
public:
virtual void SomeFunc(); // actual implementation
private:
...blah...
};


So the outside world can use IPublicClass*'s.
Far cleaner than having those nasty proxy methods,
and LESS speed penalty because you're not sending those arguments a second time.
Okay, this inhibits certain things but in those cases (inlining, template stuff) you'll need to expose the implementation anyway.

// aav

 User Rating: 1015    Report this Post to a Moderator | Link

quote:
Original post by Anonymous Poster
Also, you don't explain what the advantage of using pimpl is.

"The Pimpl idiom describes a way for making your header files impervious to change. You often hear advices like "Avoid change your public interface!" So you can modify your private interface, but how can you avoid recompilation when your header file defines the private methods. This is what the Pimpl does – Reduce compilation damages when your private interface changes."

Seems pretty straightforward to me. The pImpl is a great technique in large projects. Good article.



 User Rating: 1100   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

quote:
Original post by Anonymous Poster
Don't take this the wrong way, but if there is already an article about it at www.gotw.ca, what does your one add?

Also, you don't explain what the advantage of using pimpl is.


You will be amazed by the # of people who don't read or understand Guru of Week yet claim they are C++ gurus.

My idea is to introduce you to better C++ coding techniques. Of course I can't just have an article that says, "Go to www.gotw.ca and read item # on pimpl", can I?

As for the advantage of pimpl, it reduces make dependencies when compiling. I think I explained it pretty clearly in the abstract.

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by Anonymous Poster
If the goal you're setting up is the only one, I'd rather use an interface.

snip

So the outside world can use IPublicClass*'s.
Far cleaner than having those nasty proxy methods,
and LESS speed penalty because you're not sending those arguments a second time.
Okay, this inhibits certain things but in those cases (inlining, template stuff) you'll need to expose the implementation anyway.
// aav


This is a totally different topic.

If you need to expose the implemetation, then you are introducing a additional dependency that can be avoided using the pimpl.



 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by abdulla
to not pollute the global namespace, you could use an anonymouse namespace


I'm not sure if I understand what you mean.

If you meant to put the private implementation class in an annoymous namespace in a header file, then it accomplishes nothing.

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I think I'm another one that doesn't get why this exists. It seems to me that using an abstract base class solves this problem.

As far as I can tell, using a pImpl is effectively reimplementing the vtable.


Helpful links:
How To Ask Questions The Smart Way | Google can help with your question | Search MSDN for help with standard C or Windows functions


 User Rating: 1071   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by Void
This is a totally different topic.

If you need to expose the implemetation, then you are introducing a additional dependency that can be avoided using the pimpl.



So it is... that's why I mentioned it.

The reason why I posted about the interface/abstract baseclass method was that, as siaspete also says, the article doesn't pose any problems that make the pimpl method seem better than the above.

// aav


 User Rating: 1015    Report this Post to a Moderator | Link

In your abstract interface case, any file that includes the PrivateClass needs to recompiled if you add/remove private methods. (And somewhere you do need to include PrivateClass in order to create a pointer to the abstract interface.)

In places where your header shouldn't change (e.g. dlls), you can safely replace the dll without recompiling the client. Of course, one would probably choose COM but that's OT here.

If you still can't see the point, either try it out or read it more at the Guru of the week.

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Cheers Void. You're right, there must be some good advantage to using this, but I just can't see it at the moment.

I'll have a read about the web and see what I can find out.

At the moment though there doesn't seem like there's anything that using this does that is better than ABCs.


Helpful links:
How To Ask Questions The Smart Way | Google can help with your question | Search MSDN for help with standard C or Windows functions


 User Rating: 1071   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

The problem with ABCs is that it's difficult to create a concrete object. You can make a static "makeme" method, but that's cheezy. Besides, if the point is to insulate the user from internal details, inheritence is the wrong thing to be using. To quote Sutter himself (and this should also be etched in stone and pounded into the head of every new programmer):
"Inheritance is often overused, even by experienced developers. Always minimize coupling. If a class relationship can be expressed in more than one way, use the weakest relationship that's practical. Given that inheritance is nearly the strongest relationship you can express in C++ (second only to friendship), it's only really appropriate when there is no equivalent weaker alternative."

Composition, especially that of a single pointer to privately-defined class, is just about as weak as you can get. If you don't believe the ramifications of this, imagine you are writing a commonly-included class (say error reporting, or just trace logging) that is used by every module in your program, and that a full recompile takes about 4 hours. With the pImpl, once you set your public interface, client modules never have to recompile.

 User Rating: 1100   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

If == and () are unset why not simply separate public (user) side headers and private+public side headers ? This could be used for low level classes and no extra dereferencement is required.

I never did it before but I imagine it's the equivalent of a C lib/module where static functions are hidden to the user. Am I wrong ?

To me the only pb is potential misadressing. Thus the public data, probably required by inlined public methods, must be carefully declared ahead and not modified. But that could be part of the "interface contract". Linker/Compiler dependent issues ? I dont say it would work in all cases but in some low level cases it could be useful. But then beware private virtual methods. I am not really sure about what could happen ! LOL

I like to practice different styles depending on the hi/lo level of programming. The best thing for global efficiency AND stability.

 User Rating: 1506   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by siaspete
At the moment though there doesn't seem like there's anything that using this does that is better than ABCs.



To further clarify what stoffel has said, the main problem with the ABC is the public heritance.

What may actually happen (and often) is that your class is already a subclass. This is where you stepped into the dreaded multiple inheritance area. And with it comes lots of problems when you are using public inhertiance when the relationship is not a IS-A.

It's pretty easy to set the benefit of pimpl vs the abstract class method. Just look at the # of files that has to be recompiled when you add a private method.

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by Charles B
If == and () are unset why not simply separate public (user) side headers and private+public side headers ? This could be used for low level classes and no extra dereferencement is required.


That is the ultimate goal of the pimpl but it can't do it without the additional dereference.

I'm not sure what you mean by separating having seperate sets of headers. Unless what you mean is to replace all the private member functions with non-member functions inside it's own private implementation file, I can't see how this is possible.
(But then you need to pass the class instance around, so it's amounts to the same thing)

If you are talking about some platform specific function address rebasing scheme, then I'm not interested. 8(

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Yes, the ABC/interface case requires some kind of "creator" entity that is decoupled from the private implementation -- naturally. Otherwise the whole point would be missed.

But it's rarely a problem, you usually DO have a natural place to put those creators, in a parent manager object or something like that. OOP systems tend to be hierarchical in nature, and you always have the toplevel namespace.

This is the basis of COM and similar 'patterns', I don't personally have a problem with it. And I still think this is far less evil than definining wrapper methods for everything.

// aav


 User Rating: 1015    Report this Post to a Moderator | Link

quote:
Original post by Void
To further clarify what stoffel has said, the main problem with the ABC is the public heritance.



It is possible to solve many of these cases by templatizing the privately used baseclass (class Private : public MyBase<IFoo> etc) but yes, it's a problem.

However, I've found that inheritance can often be avoided in general, and there's a good chance you can avoid it on the publically exposed classes specifically. Public interfaces should be kept simple and in small numbers anyway.

// aav


 User Rating: 1015    Report this Post to a Moderator | Link

quote:
Original post by Anonymous Poster
This is the basis of COM and similar 'patterns', I don't personally have a problem with it. And I still think this is far less evil than definining wrapper methods for everything.


I have limited experience with COM, but from what I seen it, it turns C++ class into C interface by rebasing using really ugly macros.

Can you add private methods to an interface once it is etech in the COM? Or must you get the next version of the interface? This must be done without recompiling the client.

Say, for using classes with dlls, you would want to avoid recompiling the client, the usual(?) practice is to pass a void pointer to the dll and the dll would initialize the pointer. The pimpl would be pretty useful here.

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by Void
I have limited experience with COM, but from what I seen it, it turns C++ class into C interface by rebasing using really ugly macros.



Well MS's bloated COM can do that, but I was more comparing it to the "pattern" of having an ABC-based interface and creators. COM does not automatically mean ugly macros. It can be as simple as I've described.

quote:

Can you add private methods to an interface once it is etech in the COM? Or must you get the next version of the interface? This must be done without recompiling the client.



For this whole thing to work, the compiler must only be able to create "COM-patible" vtables. The only "contract" between the user code and the private implementation is the vtable (the public interface). So you can modify the private implementation all you want, as long as the public interface remains the same.

Most compilers on win32 should either directly produce or have an option to enable support for this "binary vtable standard".

Pimpl does not offer this kind of binary compatibility between different compilers, as it 1) doesn't use virtual functions and even if it would, 2) it uses proxy CODE to communicate with the DLL.

Again, not saying there isn't a use for Pimpl, but the problems presented so far are MUCH simpler to solve with interfaces.

// aav


 User Rating: 1015    Report this Post to a Moderator | Link

Forgot to inform you, I prefer non compiler/platform specific solutions. 8)

I think we are reaching the "apples and oranges" talk. The pimpl is not only useful for external interface but internal modules. Which is where the power shines because you don't have to recompile the whole project when you change a highly dependant module.

Though nothing is stopping you, you don't usually make a COM interface classes for private modules just to reduce code dependency.

 User Rating: 1017   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I suppose I still don't see the advantage of Pimpl. I'm not a C++ guru, but I am an enthusiast. Hey, if Stroustrup says to use abstract base classes, I think I'm gonna listen to him. HE is a C++ guru. From what I have read, one should write C++ and assume that the compiler can do its job.

I also don't see why ABCs cause a full recompilation. You put the ABC in one header file. This is included in any modules that need to know about the ABC. You don't worry yet about the implementation. Who cares?

 User Rating: 1015    Report this Post to a Moderator | Link

The article is full of errors. E.g. it claims that you can't use std::auto_ptr to hold the pointer. Of course you can. I do it all the time and it works just fine, thank you very much. An other error would be the name. It's short for "Pointer to Impl", nothing else.

 User Rating: 1015    Report this Post to a Moderator | Link

Quote:
The article is full of errors. E.g. it claims that you can't use std::auto_ptr to hold the pointer. Of course you can. I do it all the time and it works just fine, thank you very much.


The problems with std::auto_ptr are well-documented. Of course, the problems nearly all stem from users mistaken assumption that the purpose of auto_ptr is to be a smart pointer. Well, it is... but it ain't that smart. For one, only one auto_ptr can owns a pointer at any one time, so doing something like this:

MyPimplUsingClass something, another;
something = another;


Now you've confused things. The auto_ptr in something now has a valid pointer (which it took from another), while another now has a null value. Probably not what was intended. But exactly what auto_ptr is supposed to do, and I'm sure it's what the authoer was referring to.

Quote:
An other error would be the name. It's short for "Pointer to Impl", nothing else.


While we're nit-picking, wouldn't that be better stated as "Another error would be the name. It's short for 'Pointer to Implementation..." Whatever, that's certainly not official by any means. In fact, a quick Google for pimpl "private implementation" yields more results (~1000) than pimpl "pointer to implementation" (~130) plus pimpl "pointer implementation" (~340). I'll happily admit that many of the first query are not defining the abbreviation, but enough of them are to diffuse that as an "error" in the article.

I'll not pretend the article was gloriously in-depth, but Pimpl is pretty simple ().

 User Rating: 1420   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: