In the class definition, declare a (smart) pointer to the struct as the only private member variable.

The constructors for the class need to create the struct.

The destructor of the class needs to destroy the struct (possibly implicitly due to use of a smart pointer).

The assignment operator and CopyConstructor need to copy the struct appropriately or else be disabled.

It seems to me like the need for something like this reflects a less than ideal design decision in the C++ language: namely, the need to declare private members as part of the declaration that the rest of the system compiles against. DelphiLanguage has the same "feature". It would seem to make more sense to have an "interface" declaration which the rest of the system sees, with no mention of anything private to the class. The implementation portion would specify private members etc. -- KyleCordes

It's a less than ideal design decision in the CeeLanguage that's causing the problem. This would be unnecessary if the linker wasn't separated from the compiler, but alas, you don't have access to information like the size of the aggregate type at compile time except through the declaration. Therefore, you need to present the location and types of the private members so you can do things like offset calculations, PointerArithmetic, etc. -- SunirShah

Disagreed strongly. The linker being separate from the compiler is important too when attempting to compile to a known interface without a known library. Though the common example used - creating libraries which are safe upwards - isn't that big a deal, this tool has many other applications, not the least of which is writing code ignorant of the underlying implementation. -- StoneCypher

Put it this way, there is no truly "private" data in CeePlusPlus. You can always catch a glimpse of the private instance variables at compile time with sizeof(). -- JohnCarter

This is a misunderstanding of the concept of privacy, which is an organizational tool intended to help a programmer sort the parts of code which are intended to interface with the outside world from the stuff which is meant to be kept internal. TC++PL is quite clear on the point that this has nothing to do with run-time and compile-time effects which can be easily used to look at the class's guts; it's merely a method to help programmers encapsulate. -- StoneCypher

It's a significant idiom for another reason not mentioned above: operations on pointers (and auto_ptrs, for that matter) are guaranteed not to throw. This is important because it means you can write strongly exception-safe constructors, CopyConstructor and assignment operator, even if your members can throw during their construction. Granted, you can still suffer from unexpected SideEffects but you're a long way nearer exception-nirvana. -- JonKale

An even better reason for using it is creating UnitTests in legacy CeePlusPlus systems. Suppose you have an object with big hairy beasties embedded in it as instance variables....

If you include A.H, you need to compile and link all the big scary stuff _even_ though they are private. That can get you into quite a sprawl of needing to link in BigScaryMonster.o and then BiggerScarierMonster.o and then this, then that, then everybody and its snotty little brother.

You could create a MockA that doesn't have the scary stuff in and link that in your tests. Unfortunately, strange and foul things may happen if you link some of the other modules that see the real A, with the tests that see only the MockA. Bad. Bad. Bad.

Enter pimpl.

struct AImp;
class A {
public:
// Same public interface as A, but all delegated to concrete implementation.
private:
AImp * pimpl;
};

You can now create tests that can link with impunity to other real modules from the system, and you don't have to link in the scary stuff. Just a tame mock implementation. In fact, it doesn't even have to be a complete implementation. Just the bits you test. -- JohnCarter

In practice, this idiom is just a one-off SmartPointer, and there's really no point not using a general smart pointer template instead. You don't actually have to write the code to delegate every method on to the "real" object. Instead, you declare a pure abstract class:

This can go in the header because it reveals nothing about the implementation (which derives from it and so has to implement the methods). Then you write the wrapper class that holds a pointer to an ILightSwitch, and defines the -> operator to forward all method calls to the real object. And finally, you realize this pattern has nothing to do with a specific interface. It's just something that "manages" a pointer for you and ensures it is cleaned up in a predictable way. So you turn it into a reusable template, and there you are: it's a SmartPointer. -- DanielEarwicker

Yes indeed, this "hidden constructor" pattern is a must in shared libraries or DLLs that represent "plug-ins" to some core product. The only symbol that needs to be found using the platform's dynamic linking features is the "factory function" MakeLightSwitch. Also it makes using dlopen (Unix) or LoadLibrary? (Win32) a lot easier if you only have to find one entry point. Incidentally, we are well on our way to re-inventing COM here (check out Mozilla's XPCOM). -- DanielEarwicker

If you use a SmartPointer and you only have one implementation, there is no need to make any of the member functions virtual, except possibly the destructor. The run-time cost of non-virtual member function calls is much lower, and a compiler that does whole-program optimization can inline them even though they're in a separate translation unit. Here's an example:

Here, the destructor needs to be declared virtual foo so that std::auto_ptr<foo> calls foo_impl's destructor. If you use boost::shared_ptr<foo> instead, even that doesn't need to be virtual, because shared_ptr remembers how to call the correct destructor. (This doesn't improve performance or memory use, because shared_ptr is larger and slower than auto_ptr, but if you need to use shared_ptr anyway you may as well eliminate the virtual destructor.) -- BenHutchings

There's lots of good discussion and code on this idiom in LargeScaleCppSoftwareDesign. A wonderful book, even if you don't do C++ for a living.

This sounds similar to the combination of patterns I worked out for myself, which I recently christened ZitfacePattern -- KarlKnechtel

Still another thing that makes this a very useful idiom is the fact that it provides a way for you to inherit functionality from a third party library without passing any dependencies on the library to your class users. Just make your XImpl class inherit from your third party library class. Dependencies are only in your .CPP file, not the header files. -- FernandoRamos?