My class uses the PImpl idiom and looks something like this:
// In LongDescriptiveClassName.hpp
class LongDescriptiveClassName
{
public:
// Stuff...
private:
struct LongDescriptiveClassNameData;
LongDescriptiveClassNameData &Data;
};
In the .cpp file, I declare/define the private struct:
// In LongDescriptiveClassName.cpp
struct LongDescriptiveClassName::LongDescriptiveClassNameData
{
void PrivateMethod1();
void PrivateMethod2();
// and so on...
};
void LongDescriptiveClassName::LongDescriptiveClassNameData::PrivateMethod1()
{
// Stuff...
}
void LongDescriptiveClassName::LongDescriptiveClassNameData::PrivateMethod2()
{
// Stuff...
}
This is painful for me to read. Is there a way that I can abbreviate the names leading up to the private methods?
My understanding is that I can't typedef it in the .cpp file because the PImpl struct is private. Would it be an evil to use #define?
#define ShortName LongDescriptiveClassName::LongDescriptiveClassNameData
struct ShortName
{
// ...
};
void ShortName::PrivateMethod1()
// ...
This .cpp file is the only source file that would need to abbreviate it, and then only for method definitions. What do you recommend?
The class name is already a namespace, so there's no reason to give the impl such a long name:
class LongDescriptiveClassName
{
public:
// Stuff...
private:
struct Impl;
// shared_ptr is also an option if that's
// the semantics you want.
std::unique_ptr<Impl> Data;
};
// and off in the implementation, we have...
struct LongDescriptiveClassName::Impl
{
void PrivateMethod1();
void PrivateMethod2();
// and so on...
};
void LongDescriptiveClassName::Impl::PrivateMethod1()
{
// Stuff...
}
It works just fine.
Incidentally, your code is not an example of the pimpl idiom. The "p" in "pimpl" means "pointer", and this is important. A reference means that the object does not own its implementation.
It's not necessarily wrong; there are sometimes good reasons to wrap a reference in a class, but it's not the pimpl idiom.
I'm not completely sure to understand your problem but it seems that a proper use of the using keyword should help a lot. Isn't
using ShortName = LongDescriptiveClassName::LongDescriptiveClassNameData
what you are looking for ?
Note this only work is LongDescriptiveClassNameData is a type not a data.
While #Pseudonym's solution is absolutely fine, I prefer to use names with initial upper case only for types, so I think I'd just do:
class LongDescriptiveClassName {
private:
struct Data;
Data &data;
};
I like to call it Impl, or Detail (though the latter is common as a namespace detail, also).
Related
If a class has lots of private functions it seems undesirable to have them declared in the header file. It makes it harder for clients to parse the interface of the class and it increases compilation time.
One option is, of course, the pimpl idiom, but that adds a layer of indirection and also results in a memory allocation.
What follows is a example of hiding helper functions in a friend class that is defined in the implementation file.
Is there a name for this idiom?
Is there any reason not to do it?
//Foo.h
class Foo
{
public:
void FuncA();
void FuncB();
private:
int x;
// more data...
friend struct FooHelpers;
};
//Foo.cpp
struct FooHelpers
{
static void Helper1(Foo& f)
{
// manipulate private data..
f.x++; //etc.
}
// Possibly more funcs...
};
void Foo::FuncA()
{
//....
FooHelpers::Helper1(*this);
//....
}
//....
Is there a name for the idiom of using a friend class to hide what would have been private functions?
The Attorney-Client idiom.
Is there any reason not to do it?
As suggested also in some comments, here's a reason not to do it: while it provides a patterned option, it avoids dealing with the root of the problem - the design of the original class (class Foo).
In your question you write:
If a class has lots of private functions it seems undesirable to have them declared in the header file.
There's some subjectivity to this question so allow me to restate it more objectively with the following question.
Are there ways to avoid private member functions?
You pointed out one way, to use the PIMPL idiom. As also suggested in some comments, here's some more:
Refactor the original (a.k.a. client) class to instead use non-member non-friend functions or lambda expressions that manipulate your class member data through parameters - so that it doesn't need private member functions.
Split up the class into multiple smaller classes so that each of the smaller classes declares less of the original class's private member functions. Like with member data, the more private member functions a class has, the more likely - at least in my opinion - the class is violating the single responsibility principal. So this kind of effort can reduce the private member functions as well making your class design more robust.
Say we start with the following code:
//Foo.h
class Foo
{
public:
void FuncA();
void FuncB();
private:
void multiplyByTwo();
int x;
// more data...
};
//Foo.cpp
void Foo::multiplyByTwo()
{
x = x * 2;
}
void Foo::FuncA()
{
multiplyByTwo();
}
Here's an example using the first way of what this could be changed to:
//Foo.h
class Foo
{
public:
void FuncA();
void FuncB();
private:
int x;
// more data...
};
//Foo.cpp
namespace {
int multiplyByTwo(int x)
{
return x * 2;
}
}
void Foo::FuncA()
{
x = multiplyByTwo(x);
}
In addition to eliminating the declaration of multiplyByTwo as a private member function of class Foo, this change also more idiomatically expresses the intention of the multiplyByTwo function in now saying in C++ syntax what's its input and output.
I'm writing a C++ wrapper library around a number of different hardware libraries for embedded systems (firmware level), using various libraries from different vendors (C or C++). The API exposed by the header files should be vendor agnostic... all Vendor header libraries are not included in any of my header files.
A common pattern I have is making the vendor member data opaque, by only using a pointer to some "unknown" vendor struct/class/typedef/pod type.
// myclass.h
class MyClass
{
...
private:
VendorThing* vendorData;
};
and implementation (note: each implementation is vendor specific; all have the same *.h file)
// myclass_for_vendor_X.cpp
#include "vendor.h"
... {
vendorData->doSomething();
or
VendorAPICall(vendorData,...);
or whatever
The problem I have is that VendorThing can be lots of different things. It could be a class, struct, type or pod. I don't know, and I don't want to care in the header file. But if you pick the wrong one, then it doesn't compile if the vendor header file is included as well as my header file. For example, if this the actual declaration of VendorThing in "vendor.h":
typedef struct { int a; int b; } VendorThing;
Then you can't just forward-declare VendorThing as class VendorThing;. I don't care about what the type of VendorThing is at all, all I want is the public interface to think of it as void * (i.e allocate space for a pointer and that is it), and the implementation think of it using the correct pointer type.
Two solutions I have come across are the "d-pointer" method found in Qt, where you add a level of indirection by replacing VendorThing a new struct VendorThingWrapper
// myclass.h
struct VendorThingWrapper;
class MyClass
{
...
private:
VendorThingWrapper* vendorDataWrapper;
};
and in your cpp file
// myclass.cpp
#include "vendor.h"
struct VendorThingWrapper {
VendorThing* vendorData;
};
... {
vendorDataWrapper->vendorData->doSomething();
}
but this adds a second pointer dereference, which is not a huge deal, but as this is targeting embedded systems, I don't want to add that overhead just because the language can't do what I want.
The other thing is just declare it void
// myclass.h
class MyClass
{
...
private:
void* vendorDataUntyped;
};
and in the implememtation
//myclass.cpp
#include "vendor.h"
#define vendorData ((VendorThing*)vendorDataUntyped)
... {
vendorData->doSomething();
}
but #define's always leave a bad taste in my mouth. There must be something better.
You can avoid the additional pointer dereference by using:
#include "vendor.h"
struct VendorThingWrapper : public VendorThing {};
Of course, at that point, it makes more sense to use the name MyClassData instead of VendorThingWrapper.
MyClass.h:
struct MyClassData;
class MyClass
{
public:
MyClass();
~MyClass();
private:
MyClassData* myClassData;
};
MyClass.cpp:
struct MyClassData : public VendorThing {};
MyClass::MyClass() : myClassData(new MyClassData())
{
}
MyClass::~MyClass()
{
delete myClassData;
}
Update
I was able to compile and build the following program. The unnamed struct is not a problem.
struct MyClassData;
class MyClass
{
public:
MyClass();
~MyClass();
private:
MyClassData* myClassData;
};
typedef struct { int a; int b; } VendorThing;
struct MyClassData : public VendorThing
{
};
MyClass::MyClass() : myClassData(new MyClassData())
{
myClassData->a = 10;
myClassData->b = 20;
}
MyClass::~MyClass()
{
delete myClassData;
}
int main() {}
If you are willing to go the route of the VendorThingWrapper, then you simply allow the wrapper to contain the data itself, rather than a pointer to it. This gives you the abstraction layer and avoids the extra dereference.
// myclass.cpp
#include "vendor.h"
struct VendorThingWrapper {
VendorThing vendorData;
};
... {
vendorDataWrapper->vendorData.doSomething();
}
In my class I have the need to keep a pointer to a structure which is defined in a library I use to implement it. Since this library is only used within the implementation file I would like to avoid including it in the header directly. At the same time I want to avoid polluting the namespace. Thus I would like to do:
/* HEADER */
class Foo {
private:
struct ImplementationDetail;
ImplementationDetail * p;
};
/* SOURCE */
#include <Library.h>
using Foo::ImplementationDetail = Library::SomeStruct;
But this doesn't work, and I'm currently falling back on PIMPL:
/* HEADER */
class Foo {
private:
struct ImplementationDetail;
ImplementationDetail * p_;
};
/* SOURCE */
#include <Library.h>
struct ImplementationDetail {
Library::SomeStruct * realp_;
}
Is there a way to avoid the double dereference? Is the reason for my non-working first solution due to unknown pointer sizes?
// Header
class Foo {
private:
struct ImplementationDetail;
ImplementationDetail * p;
};
// Source
#include <Library.h>
struct Foo::ImplementationDetail :public Library::SomeStruct {
// ....
};
and allocating/deallocating/dereferencing the pointer in this source file only should work just fine.
This is an incorrect declaration:
using Foo::ImplementationDetail = Library::SomeStruct;
using doesn't work this way. In C++11 using cannot create an alias for a name in one namespace to a name in another namespace. In C++03, all using does is bring some other namespace in to global visibility in the current translation unit. It's not used to create aliases in C++03, as you seem to want to do here.
pimpl is the de-facto method for doing what you're trying to do, but in your header file instead of trying to use a ImplementationDetail*, I would use a simple void*. Using a void* in this manner is guaranteed to be correct according to the Standard:
class Foo {
private:
void * pImpl;
Use static_cast2 to go from a void* to your actual type:
void Foo::Bar()
{
Library::SomeStruct* thingy = static_cast <Library::SomeStruct*> (pImpl);
// ...
}
You can avoid using the void* in a conformant way by forward-declaring your library type:
namespace Library
{
struct SomeStruct;
};
class Foo
{
private:
Library::SomeStruct* pStruct;
};
And then no ugly cast is needed in the implementation.
2 Use static_cast : Or reinterpret_cast
The reason you can't take your first approach is that in the header you tell the compiler "I'm declaring a nested class within Foo and it's called ImplementationDetail". Then you proceed to say "wait wait, it's NOT a new class, it's an alias to this other thing entirely" and understandably the compiler gets confused.
Have you tried just forward declaring the library's implementation and using that instead of trying to create an alias?
In your first code you declared the nested type ImplementationDetail to be a struct which will be define inside Foo. Trying to alias it can't work because that would be a type defined elsewhere and, actually, you private structure isn't accessible from outside the class. Wrapping a pointer to another object inside seems unecessary: you could instead either embed the Library::SomeStruct by value or have your ImplementationDetail derive from Library::SomeStruct:
struct ImplementationDetail
: Library::SomeStruct {
using Library::SomeStruct::SomeStruct;
};
(the using declaration is just used to inherit all the constructors from Library::SomeStruct).
I think this is not possible without casting.
Basically there are two ways to do it:
1) Define p_ as void* and cast it in every function that uses it.
/* HEADER */
class Foo {
private:
void* p;
};
/* SOURCE */
#include <Library.h>
void Foo::AnyFunc()
{
Library::SomeStruct* pImpl = reinterpret_cast<Library::SomeStruct*>(p);
...
}
2) Create a "shadowing"-class of your class (in the .cpp-file) with all members cloned and p_ defined as Library::SomeStruct. Then cast the this-pointer to this shadowing class. This is of course a quite insecure and dirty hack which I don't recommend...
/* HEADER */
class Foo {
private:
void* p;
};
/* SOURCE */
#include <Library.h>
class FooImpl
{
public:
void AnyFunc() { p->DoSomething(); }
private:
Library::SomeStruct* p;
}
void Foo::AnyFunc()
{
FooImpl* pImpl = reinterpret_cast<FooImpl*>(this);
pImpl->AnyFunc();
}
This exploits memory structure and is therefore quite fragile (all members need to be in the same order and when you add or remove members, you need to update ShadowFoo, too). I mentioned this just for completeness.
3) This brings us to yet another, but more simple way: create the implementation in the source file and initialize it in the constructor with the void*-pointer:
/* HEADER */
class Foo {
private:
void* p;
};
/* SOURCE */
#include <Library.h>
class FooImpl
{
public:
FooImpl(void* pSomeStruct)
{
p = reinterpret_cast<Library::SomeStruct*>(pSomeStruct);
}
void AnyFunc() { p->DoSomething(); }
private:
Library::SomeStruct* p;
}
void Foo::AnyFunc()
{
FooImpl impl = FooImpl(p);
impl.AnyFunc();
}
I am trying to use the pimpl pattern and define the implementation class in an anonymous namespace. Is this possible in C++? My failed attempt is described below.
Is it possible to fix this without moving the implementation into a namespace with a name (or the global one)?
class MyCalculatorImplementation;
class MyCalculator
{
public:
MyCalculator();
int CalculateStuff(int);
private:
MyCalculatorImplementation* pimpl;
};
namespace // If i omit the namespace, everything is OK
{
class MyCalculatorImplementation
{
public:
int Calculate(int input)
{
// Insert some complicated calculation here
}
private:
int state[100];
};
}
// error C2872: 'MyCalculatorImplementation' : ambiguous symbol
MyCalculator::MyCalculator(): pimpl(new MyCalculatorImplementation)
{
}
int MyCalculator::CalculateStuff(int x)
{
return pimpl->Calculate(x);
}
No, the type must be at least declared before the pointer type can be used, and putting anonymous namespace in the header won't really work. But why would you want to do that, anyway? If you really really want to hide the implementation class, make it a private inner class, i.e.
// .hpp
struct Foo {
Foo();
// ...
private:
struct FooImpl;
boost::scoped_ptr<FooImpl> pimpl;
};
// .cpp
struct Foo::FooImpl {
FooImpl();
// ...
};
Foo::Foo() : pimpl(new FooImpl) { }
Yes. There is a work around for this. Declare the pointer in the header file as void*, then use a reinterpret cast inside your implementation file.
Note: Whether this is a desirable work-around is another question altogether. As is often said, I will leave that as an exercise for the reader.
See a sample implementation below:
class MyCalculator
{
public:
MyCalculator();
int CalculateStuff(int);
private:
void* pimpl;
};
namespace // If i omit the namespace, everything is OK
{
class MyCalculatorImplementation
{
public:
int Calculate(int input)
{
// Insert some complicated calculation here
}
private:
int state[100];
};
}
MyCalculator::MyCalculator(): pimpl(new MyCalculatorImplementation)
{
}
MyCalaculator::~MyCalaculator()
{
// don't forget to cast back for destruction!
delete reinterpret_cast<MyCalculatorImplementation*>(pimpl);
}
int MyCalculator::CalculateStuff(int x)
{
return reinterpret_cast<MyCalculatorImplementation*>(pimpl)->Calculate(x);
}
No, you can't do that. You have to forward-declare the Pimpl class:
class MyCalculatorImplementation;
and that declares the class. If you then put the definition into the unnamed namespace, you are creating another class (anonymous namespace)::MyCalculatorImplementation, which has nothing to do with ::MyCalculatorImplementation.
If this was any other namespace NS, you could amend the forward-declaration to include the namespace:
namespace NS {
class MyCalculatorImplementation;
}
but the unnamed namespace, being as magic as it is, will resolve to something else when that header is included into other translation units (you'd be declaring a new class whenever you include that header into another translation unit).
But use of the anonymous namespace is not needed here: the class declaration may be public, but the definition, being in the implementation file, is only visible to code in the implementation file.
If you actually want a forward declared class name in your header file and the implementation in an anonymous namespace in the module file, then make the declared class an interface:
// header
class MyCalculatorInterface;
class MyCalculator{
...
MyCalculatorInterface* pimpl;
};
//module
class MyCalculatorInterface{
public:
virtual int Calculate(int) = 0;
};
int MyCalculator::CalculateStuff(int x)
{
return pimpl->Calculate(x);
}
namespace {
class MyCalculatorImplementation: public MyCalculatorInterface {
...
};
}
// Only the ctor needs to know about MyCalculatorImplementation
// in order to make a new one.
MyCalculator::MyCalculator(): pimpl(new MyCalculatorImplementation)
{
}
markshiz and quamrana provided the inspiration for the solution below.
class Implementation, is intended to be declared in a global header file and serves as a void* for any pimpl application in your code base. It is not in an anonymous/unnamed namespace, but since it only has a destructor the namespace pollution remains acceptably limited.
class MyCalculatorImplementation derives from class Implementation. Because pimpl is declared as std::unique_ptr<Implementation> there is no need to mention MyCalculatorImplementation in any header file. So now MyCalculatorImplementation can be implemented in an anonymous/unnamed namespace.
The gain is that all member definitions in MyCalculatorImplementation are in the anonymous/unnamed namespace. The price you have to pay, is that you must convert Implementation to MyCalculatorImplementation. For that purpose a conversion function toImpl() is provided.
I was doubting whether to use a dynamic_cast or a static_cast for the conversion. I guess the dynamic_cast is the typical prescribed solution; but static_cast will work here as well and is possibly a little more performant.
#include <memory>
class Implementation
{
public:
virtual ~Implementation() = 0;
};
inline Implementation::~Implementation() = default;
class MyCalculator
{
public:
MyCalculator();
int CalculateStuff(int);
private:
std::unique_ptr<Implementation> pimpl;
};
namespace // Anonymous
{
class MyCalculatorImplementation
: public Implementation
{
public:
int Calculate(int input)
{
// Insert some complicated calculation here
}
private:
int state[100];
};
MyCalculatorImplementation& toImpl(Implementation& impl)
{
return dynamic_cast<MyCalculatorImplementation&>(impl);
}
}
// no error C2872 anymore
MyCalculator::MyCalculator() : pimpl(std::make_unique<MyCalculatorImplementation>() )
{
}
int MyCalculator::CalculateStuff(int x)
{
return toImpl(*pimpl).Calculate(x);
}
Consider the following:
PImpl.hpp
class Impl;
class PImpl
{
Impl* pimpl;
PImpl() : pimpl(new Impl) { }
~PImpl() { delete pimpl; }
void DoSomething();
};
PImpl.cpp
#include "PImpl.hpp"
#include "Impl.hpp"
void PImpl::DoSomething() { pimpl->DoSomething(); }
Impl.hpp
class Impl
{
int data;
public:
void DoSomething() {}
}
client.cpp
#include "Pimpl.hpp"
int main()
{
PImpl unitUnderTest;
unitUnderTest.DoSomething();
}
The idea behind this pattern is that Impl's interface can change, yet clients do not have to be recompiled. Yet, I fail to see how this can truly be the case. Let's say I wanted to add a method to this class -- clients would still have to recompile.
Basically, the only kinds of changes like this that I can see ever needing to change the header file for a class for are things for which the interface of the class changes. And when that happens, pimpl or no pimpl, clients have to recompile.
What kinds of editing here give us benefits in terms of not recompiling client code?
The main advantage is that the clients of the interface aren't forced to include the headers for all your class's internal dependencies. So any changes to those headers don't cascade into a recompile of most of your project. Plus general idealism about implementation-hiding.
Also, you wouldn't necessarily put your impl class in its own header. Just make it a struct inside the single cpp and make your outer class reference its data members directly.
Edit: Example
SomeClass.h
struct SomeClassImpl;
class SomeClass {
SomeClassImpl * pImpl;
public:
SomeClass();
~SomeClass();
int DoSomething();
};
SomeClass.cpp
#include "SomeClass.h"
#include "OtherClass.h"
#include <vector>
struct SomeClassImpl {
int foo;
std::vector<OtherClass> otherClassVec; //users of SomeClass don't need to know anything about OtherClass, or include its header.
};
SomeClass::SomeClass() { pImpl = new SomeClassImpl; }
SomeClass::~SomeClass() { delete pImpl; }
int SomeClass::DoSomething() {
pImpl->otherClassVec.push_back(0);
return pImpl->otherClassVec.size();
}
There has been a number of answers... but no correct implementation so far. I am somewhat saddened that examples are incorrect since people are likely to use them...
The "Pimpl" idiom is short for "Pointer to Implementation" and is also referred to as "Compilation Firewall". And now, let's dive in.
1. When is an include necessary ?
When you use a class, you need its full definition only if:
you need its size (attribute of your class)
you need to access one of its method
If you only reference it or have a pointer to it, then since the size of a reference or pointer does not depend on the type referenced / pointed to you need only declare the identifier (forward declaration).
Example:
#include "a.h"
#include "b.h"
#include "c.h"
#include "d.h"
#include "e.h"
#include "f.h"
struct Foo
{
Foo();
A a;
B* b;
C& c;
static D d;
friend class E;
void bar(F f);
};
In the above example, which includes are "convenience" includes and could be removed without affecting the correctness ? Most surprisingly: all but "a.h".
2. Implementing Pimpl
Therefore, the idea of Pimpl is to use a pointer to the implementation class, so as not to need to include any header:
thus isolating the client from the dependencies
thus preventing compilation ripple effect
An additional benefit: the ABI of the library is preserved.
For ease of use, the Pimpl idiom can be used with a "smart pointer" management style:
// From Ben Voigt's remark
// information at:
// http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Checked_delete
template<class T>
inline void checked_delete(T * x)
{
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}
template <typename T>
class pimpl
{
public:
pimpl(): m(new T()) {}
pimpl(T* t): m(t) { assert(t && "Null Pointer Unauthorized"); }
pimpl(pimpl const& rhs): m(new T(*rhs.m)) {}
pimpl& operator=(pimpl const& rhs)
{
std::auto_ptr<T> tmp(new T(*rhs.m)); // copy may throw: Strong Guarantee
checked_delete(m);
m = tmp.release();
return *this;
}
~pimpl() { checked_delete(m); }
void swap(pimpl& rhs) { std::swap(m, rhs.m); }
T* operator->() { return m; }
T const* operator->() const { return m; }
T& operator*() { return *m; }
T const& operator*() const { return *m; }
T* get() { return m; }
T const* get() const { return m; }
private:
T* m;
};
template <typename T> class pimpl<T*> {};
template <typename T> class pimpl<T&> {};
template <typename T>
void swap(pimpl<T>& lhs, pimpl<T>& rhs) { lhs.swap(rhs); }
What does it have that the others didn't ?
It simply obeys the Rule of Three: defining the Copy Constructor, Copy Assignment Operator and Destructor.
It does so implementing the Strong Guarantee: if the copy throws during an assignment, then the object is left unchanged. Note that the destructor of T should not throw... but then, that is a very common requirement ;)
Building on this, we can now define Pimpl'ed classes somewhat easily:
class Foo
{
public:
private:
struct Impl;
pimpl<Impl> mImpl;
}; // class Foo
Note: the compiler cannot generate a correct constructor, copy assignment operator or destructor here, because doing so would require access to Impl definition. Therefore, despite the pimpl helper, you will need to define manually those 4. However, thanks to the pimpl helper the compilation will fail, instead of dragging you into the land of undefined behavior.
3. Going Further
It should be noted that the presence of virtual functions is often seen as an implementation detail, one of the advantages of Pimpl is that we have the correct framework in place to leverage the power of the Strategy Pattern.
Doing so requires that the "copy" of pimpl be changed:
// pimpl.h
template <typename T>
pimpl<T>::pimpl(pimpl<T> const& rhs): m(rhs.m->clone()) {}
template <typename T>
pimpl<T>& pimpl<T>::operator=(pimpl<T> const& rhs)
{
std::auto_ptr<T> tmp(rhs.m->clone()); // copy may throw: Strong Guarantee
checked_delete(m);
m = tmp.release();
return *this;
}
And then we can define our Foo like so
// foo.h
#include "pimpl.h"
namespace detail { class FooBase; }
class Foo
{
public:
enum Mode {
Easy,
Normal,
Hard,
God
};
Foo(Mode mode);
// Others
private:
pimpl<detail::FooBase> mImpl;
};
// Foo.cpp
#include "foo.h"
#include "detail/fooEasy.h"
#include "detail/fooNormal.h"
#include "detail/fooHard.h"
#include "detail/fooGod.h"
Foo::Foo(Mode m): mImpl(FooFactory::Get(m)) {}
Note that the ABI of Foo is completely unconcerned by the various changes that may occur:
there is no virtual method in Foo
the size of mImpl is that of a simple pointer, whatever what it points to
Therefore your client need not worry about a particular patch that would add either a method or an attribute and you need not worry about the memory layout etc... it just naturally works.
With the PIMPL idiom, if the internal implementation details of the IMPL class changes, the clients do not have to be rebuilt. Any change in the interface of the IMPL (and hence header file) class obviously would require the PIMPL class to change.
BTW,
In the code shown, there is a strong coupling between IMPL and PIMPL. So any change in class implementation of IMPL also would cause a need to rebuild.
Consider something more realistic and the benefits become more notable. Most of the time that I have used this for compiler firewalling and implementation hiding, I define the implementation class within the same compilation unit that visible class is in. In your example, I wouldn't have Impl.h or Impl.cpp and Pimpl.cpp would look something like:
#include <iostream>
#include <boost/thread.hpp>
class Impl {
public:
Impl(): data(0) {}
void setData(int d) {
boost::lock_guard l(lock);
data = d;
}
int getData() {
boost::lock_guard l(lock);
return data;
}
void doSomething() {
int d = getData();
std::cout << getData() << std::endl;
}
private:
int data;
boost::mutex lock;
};
Pimpl::Pimpl(): pimpl(new Impl) {
}
void Pimpl::doSomething() {
pimpl->doSomething();
}
Now no one needs to know about our dependency on boost. This gets more powerful when mixed together with policies. Details like threading policies (e.g., single vs multi) can be hidden by using variant implementations of Impl behind the scenes. Also notice that there are a number of additional methods available in Impl that aren't exposed. This also makes this technique good for layering your implementation.
In your example, you can change the implementation of data without having to recompile the clients. This would not be the case without the PImpl intermediary. Likewise, you could change the signature or name of Imlp::DoSomething (to a point), and the clients wouldn't have to know.
In general, anything that can be declared private (the default) or protected in Impl can be changed without recompiling the clients.
In non-Pimpl class headers the .hpp file defines the public and private components of your class all in one big bucket.
Privates are closely coupled to your implementation, so this means your .hpp file really can give away a lot about your internal implementation.
Consider something like the threading library you choose to use privately inside the class. Without using Pimpl, the threading classes and types might be encountered as private members or parameters on private methods. Ok, a thread library might be a bad example but you get the idea: The private parts of your class definition should be hidden away from those who include your header.
That's where Pimpl comes in. Since the public class header no longer defines the "private parts" but instead has a Pointer to Implementation, your private world remains hidden from logic which "#include"s your public class header.
When you change your private methods (the implementation), you are changing the stuff hidden beneath the Pimpl and therefore clients of your class don't need to recompile because from their perspective nothing has changed: They no longer see the private implementation members.
http://www.gotw.ca/gotw/028.htm
Not all classes benefit from p-impl. Your example has only primitive types in its internal state which explains why there's no obvious benefit.
If any of the members had complex types declared in another header, you can see that p-impl moves the inclusion of that header from your class's public header to the implementation file, since you form a raw pointer to an incomplete type (but not an embedded field nor a smart pointer). You could just use raw pointers to all your member variables individually, but using a single pointer to all the state makes memory management easier and improves data locality (well, there's not much locality if all those types use p-impl in turn).