Finding my way around a "circular include" when using derived classes - c++

Basically, I have a base class called materials. Materials has many virtual functions, one of them is called a "Double DVD" (Which is a type of material, but is made up of two DVD's which are another material).
So at first I thought I'd store it as either a pair/vector of materials in a derived class called "Set" and have a virtual function defined in material.h that would return a vector of pointers to the two (or more) DVD objects stored.
virtual std::vector<DVD *> getPointers() { return std::vector<DVD *>(); }
However, the problem is that this necessitated the inclusion of "DVD.h" into Materials.h like this:
#ifndef CWK_MAT_H
#define CWK_MAT_H
#include "DVD.h"
#include <string>
#include <vector>
namespace MATERIALS
{
This caused the code to break in absolutely spectacular ways. Is there any way to get around this problem? I need the virtual method to get the pointers to be in the Materials class so that I can access it from this vector:
std::vector<Material *> vect;
As in
vect[1]->getPointers()
I tried to change it to a vector of materials but then it breaks (For some reason makes Visual Studio basically freeze, saying it's updating IntelliSense forever) when I change it to that in the derived class "set" (Set derives from Material, DoubleDVD derives from Set)
Is there any way to do this?

You can forward declare any class that you only use pointers or references to, instead of including the .h file with the full type information. simply type class DVD; before you use the vector of DVD pointers. A forward declaration is basically telling the compiler "hey, trust me, this type exists and I'll tell you more about it when you actually need that information". It works because pointers (and references, which are basically just fancy pointers) are always the same size, so the compiler doesn't actually NEED any more information to deal with them.
https://stackoverflow.com/a/4757718/493106
Also, by putting the code for functions in a .cpp file instead (where possible - templated class methods are sometimes not possible to do this with), you get rid of a lot of situations where you end up with circular includes, since nothing should be #include'ing .cpp files.

Related

Is forward declaring a class a correct way to hide the implementation? [duplicate]

This question already has answers here:
Is the PIMPL idiom really used in practice?
(12 answers)
Closed 8 years ago.
Backgrounder:
The PIMPL Idiom (Pointer to IMPLementation) is a technique for implementation hiding in which a public class wraps a structure or class that cannot be seen outside the library the public class is part of.
This hides internal implementation details and data from the user of the library.
When implementing this idiom why would you place the public methods on the pimpl class and not the public class since the public classes method implementations would be compiled into the library and the user only has the header file?
To illustrate, this code puts the Purr() implementation on the impl class and wraps it as well.
Why not implement Purr directly on the public class?
// header file:
class Cat {
private:
class CatImpl; // Not defined here
CatImpl *cat_; // Handle
public:
Cat(); // Constructor
~Cat(); // Destructor
// Other operations...
Purr();
};
// CPP file:
#include "cat.h"
class Cat::CatImpl {
Purr();
... // The actual implementation can be anything
};
Cat::Cat() {
cat_ = new CatImpl;
}
Cat::~Cat() {
delete cat_;
}
Cat::Purr(){ cat_->Purr(); }
CatImpl::Purr(){
printf("purrrrrr");
}
I think most people refer to this as the Handle Body idiom. See James Coplien's book Advanced C++ Programming Styles and Idioms. It's also known as the Cheshire Cat because of Lewis Caroll's character that fades away until only the grin remains.
The example code should be distributed across two sets of source files. Then only Cat.h is the file that is shipped with the product.
CatImpl.h is included by Cat.cpp and CatImpl.cpp contains the implementation for CatImpl::Purr(). This won't be visible to the public using your product.
Basically the idea is to hide as much as possible of the implementation from prying eyes.
This is most useful where you have a commercial product that is shipped as a series of libraries that are accessed via an API that the customer's code is compiled against and linked to.
We did this with the rewrite of IONA's Orbix 3.3 product in 2000.
As mentioned by others, using his technique completely decouples the implementation from the interface of the object. Then you won't have to recompile everything that uses Cat if you just want to change the implementation of Purr().
This technique is used in a methodology called design by contract.
Because you want Purr() to be able to use private members of CatImpl. Cat::Purr() would not be allowed such an access without a friend declaration.
Because you then don't mix responsibilities: one class implements, one class forwards.
For what is worth, it separates the implementation from the interface. This is usually not very important in small size projects. But, in large projects and libraries, it can be used to reduce the build times significantly.
Consider that the implementation of Cat may include many headers, may involve template meta-programming which takes time to compile on its own. Why should a user, who just wants to use the Cat have to include all that? Hence, all the necessary files are hidden using the pimpl idiom (hence the forward declaration of CatImpl), and using the interface does not force the user to include them.
I'm developing a library for nonlinear optimization (read "lots of nasty math"), which is implemented in templates, so most of the code is in headers. It takes about five minutes to compile (on a decent multi-core CPU), and just parsing the headers in an otherwise empty .cpp takes about a minute. So anyone using the library has to wait a couple of minutes every time they compile their code, which makes the development quite tedious. However, by hiding the implementation and the headers, one just includes a simple interface file, which compiles instantly.
It does not necessarily have anything to do with protecting the implementation from being copied by other companies - which wouldn't probably happen anyway, unless the inner workings of your algorithm can be guessed from the definitions of the member variables (if so, it is probably not very complicated and not worth protecting in the first place).
If your class uses the PIMPL idiom, you can avoid changing the header file on the public class.
This allows you to add/remove methods to the PIMPL class, without modifying the external class's header file. You can also add/remove #includes to the PIMPL too.
When you change the external class's header file, you have to recompile everything that #includes it (and if any of those are header files, you have to recompile everything that #includes them, and so on).
Typically, the only reference to a PIMPL class in the header for the owner class (Cat in this case) would be a forward declaration, as you have done here, because that can greatly reduce the dependencies.
For example, if your PIMPL class has ComplicatedClass as a member (and not just a pointer or reference to it) then you would need to have ComplicatedClass fully defined before its use. In practice, this means including file "ComplicatedClass.h" (which will also indirectly include anything ComplicatedClass depends on). This can lead to a single header fill pulling in lots and lots of stuff, which is bad for managing your dependencies (and your compile times).
When you use the PIMPL idiom, you only need to #include the stuff used in the public interface of your owner type (which would be Cat here). Which makes things better for people using your library, and means you don't need to worry about people depending on some internal part of your library - either by mistake, or because they want to do something you don't allow, so they #define private public before including your files.
If it's a simple class, there's usually isn't any reason to use a PIMPL, but for times when the types are quite big, it can be a big help (especially in avoiding long build times).
Well, I wouldn't use it. I have a better alternative:
File foo.h
class Foo {
public:
virtual ~Foo() { }
virtual void someMethod() = 0;
// This "replaces" the constructor
static Foo *create();
}
File foo.cpp
namespace {
class FooImpl: virtual public Foo {
public:
void someMethod() {
//....
}
};
}
Foo *Foo::create() {
return new FooImpl;
}
Does this pattern have a name?
As someone who is also a Python and Java programmer, I like this a lot more than the PIMPL idiom.
Placing the call to the impl->Purr inside the .cpp file means that in the future you could do something completely different without having to change the header file.
Maybe next year they discover a helper method they could have called instead and so they can change the code to call that directly and not use impl->Purr at all. (Yes, they could achieve the same thing by updating the actual impl::Purr method as well, but in that case you are stuck with an extra function call that achieves nothing but calling the next function in turn.)
It also means the header only has definitions and does not have any implementation which makes for a cleaner separation, which is the whole point of the idiom.
We use the PIMPL idiom in order to emulate aspect-oriented programming where pre, post and error aspects are called before and after the execution of a member function.
struct Omg{
void purr(){ cout<< "purr\n"; }
};
struct Lol{
Omg* omg;
/*...*/
void purr(){ try{ pre(); omg-> purr(); post(); }catch(...){ error(); } }
};
We also use a pointer-to-base class to share different aspects between many classes.
The drawback of this approach is that the library user has to take into account all the aspects that are going to be executed, but only sees his/her class. It requires browsing the documentation for any side effects.
I just implemented my first PIMPL class over the last couple of days. I used it to eliminate problems I was having, including file *winsock2.*h in Borland Builder. It seemed to be screwing up struct alignment and since I had socket things in the class private data, those problems were spreading to any .cpp file that included the header.
By using PIMPL, winsock2.h was included in only one .cpp file where I could put a lid on the problem and not worry that it would come back to bite me.
To answer the original question, the advantage I found in forwarding the calls to the PIMPL class was that the PIMPL class is the same as what your original class would have been before you pimpl'd it, plus your implementations aren't spread over two classes in some weird fashion. It's much clearer to implement the public members to simply forward to the PIMPL class.
Like Mr Nodet said, one class, one responsibility.
I don't know if this is a difference worth mentioning but...
Would it be possible to have the implementation in its own namespace and have a public wrapper / library namespace for the code the user sees:
catlib::Cat::Purr(){ cat_->Purr(); }
cat::Cat::Purr(){
printf("purrrrrr");
}
This way all library code can make use of the cat namespace and as the need to expose a class to the user arises a wrapper could be created in the catlib namespace.
I find it telling that, in spite of how well-known the PIMPL idiom is, I don't see it crop up very often in real life (e.g., in open source projects).
I often wonder if the "benefits" are overblown; yes, you can make some of your implementation details even more hidden, and yes, you can change your implementation without changing the header, but it's not obvious that these are big advantages in reality.
That is to say, it's not clear that there's any need for your implementation to be that well hidden, and perhaps it's quite rare that people really do change only the implementation; as soon as you need to add new methods, say, you need to change the header anyway.

Problem with cross #include across header files with classes

Working on a simple game in c++ but I keep stumbling on a cross #include problem. Essentially the problem is like this:
I have a Chunk class that depends on Tile and Entity but Entity also depends on Chunk.
Entity.hpp
#include "Chunk.hpp"
class Entity {
public:
Chunk in_chunk;
};
Chunk.hpp
#include "Entity.hpp" // <-- not possible
class Chunk {
public:
std::vector<std::vector<Tile>> tiles;
std::vector<Entity> needs_update;
};
Now I know this question has been asked before and that this can be solved by using forward declarations and pointing to the class, but, as far as I am aware, this will also mean that everytime I need to access this vector filled with Tiles and its needs_update member I will need to do so by using pointers.
This seems like a very bad solution and I feel like there must be a better way.
So, is the only solution by pointing to the class or is there another way to get around this?
Mind you, I am quite new to c++ and just starting to grasp the concepts of pointers and references, if I am missing something trivial here please point me in the right direction and perhaps I can fix this myself.
So, is the only solution by pointing to the class or is there another way to get around this?
Forward declarations do not require usage of pointers. See fixed example on wandbox.
(Since C++17 std::vector actually can hold incomplete (forward declared) types).
Never the less, your example is "strange". Entity is an owner of Chunk, but Chunk contains Entities by value? It seems that either Entity should refer to a chunk (by reference/pointer or some other mechanism like id) or Chunk should refer to Entities that needs to be updated.
Right now it is something like this:
Every entity contains (distinct) Chunk.
Every Chunk contains two-dimensional vector of (distinct) tiles and vector of (distinct) Entities.
Every Entity from that vector contains (distinct) Chunk and so on.
If two entities should be able to "refer" to one chunk then that chunk should be outside of an entities. If two Chunks should be able to "refer" to same entities then that Entities should be stored outside Chunks and Chunk refer to them by pointer, reference, smart-pointer or an id.
What you have there is a circular dependency, which means that each file includes itself. The most common way to resolve this is by using forward declarations.
as far as I am aware, this will also mean that everytime I need to access this vector filled with Tiles and its needs_update member I will need to do so by using pointers
Nope, not at all. What your doing by a forward declaration is that you tell the compiler "Hey dude, there's a class/ struct named 'something' somewhere. Just leave it to the linker to figure it out". Then the compiler compiles it fine and its the duty of the linker to link them to the class definition (the linker will throw an error if it cant find the definition).
The only down side is that you need to include the class header if your planning on accessing the members of that forward declared class/ struct.
So, is the only solution by pointing to the class or is there another way to get around this?
My approach would be something like this,
Lets say that Chunk.hpp has the forward declaration of Entity. Then when accessing the members of Entity using a function, move the function definition to a source file (as you would normally do except for templated classes) and include the Entity.hpp file there so that it can access the member functions of Entity.

What does "class ClassName;" mean when put in header file of other class definition?

I am a bit confused about this line of code class TreeItem;. class TreeItem; is defined in other files not included in this file.
I would must look this question up in a book, but I am sure answer for this question is very simple.
#ifndef TREEMODEL_H
#define TREEMODEL_H
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant>
class TreeItem; //here, what does this do??
//! [0]
class TreeModel : public QAbstractItemModel
{
...
public:
...
private:
...
};
//! [2]
#endif // TREEMODEL_H
It is a forward declaration, and it is useful to enable to have pointers to TreeItem-s in some internal structures, etc.
Forward declarations are notably needed when you have co-recursive definitions; e.g. a struct foo containing pointers to struct bar which contains pointers to struct foo, etc... You might even declare these struct-s and define the functions operating on them in different translations units.
It is common practice, both in C and in C++, to forward declare some struct (or class) and to have variables which are pointers to it, and declare (and possibly call) functions handing such pointers.
Of course, some other file (or translation unit) would declare such opaque data structures and implement operations on it.
This is a common way to implement abstract data types.
BTW, there generally is a very common example of that in standard C. The FILE type from <stdio.h> is quite often some opaque (or at least, well hidden by many header files) struct (and you obviously don't need to know the internals of it to use <stdio.h> functions like fprintf)
In your (Qt's) case, you don't want to #include <QTreeItem> -or whatever header file is declaring class TreeItem- in this QTreeModel header file. If you did, that would add an additional header dependency (you don't need to recompile TreeModel code when TreeItem implementation has changed!) and would slow down compilation.
In smaller software projects, you might simply have a single header file and define all the struct inside.
It is called forward declaration.
Wikipedia says as follows:
In C++, classes can be forward-declared if you only need to use the
pointer-to-that-class type (since all object pointers are the same
size, and this is what the compiler cares about). This is especially
useful inside class definitions, e.g. if a class contains a member
that is a pointer to another class; to avoid circular references (i.e.
that class might also contain a member that is a pointer to this
class), we simply forward-declare the classes instead.
Forward declaration of a class is not sufficient if you need to use
the actual class type, for example, if you have a member whose type is
that class directly (not a pointer), or if you need to use it as a
base class, or if you need to use the methods of the class in a
method.

C++, removing #include<vector> or #include<string> in class header

I want to remove, if possible, the includes of both <vector> and <string> from my class header file. Both string and vector are return types of functions declared in the header file.
I was hoping I could do something like:
namespace std {
template <class T>
class vector;
}
And, declare the vector in the header and include it in the source file.
Is there a reference covering situations where you must include in the header, and situations where you can pull the includes into the source file?
You cannot safely forward declare STL templates, at least if you want to do it portably and safely. The standard is clear about the minimum requirements for each of the STL element, but leaves room for implemtation extensions that might add extra template parameters as long as those have default values. That is: the standard states that std::vector is a template that takes at least 2 parameters (type and allocator) but can have any number of extra arguments in a standard compliant implementation.
What is the point of not including string and vector headers? Surely whoever is going to use your class must have already included it since it is on your interface.
When you ask about a reference to decide when to include and when to forward declare, my advice would be: include everything that is part of your interface, forward declare internal details.
There are more issues here that plain compilation performance. If you push the include of a type that is in your public (or protected) interface outside of the header you will be creating dependencies on the order of includes. Users must know that they must include string before including your header, so you are giving them one more thing to worry about.
What things should be included in the implementation file: implementation details, loggers, elements that don't affect the interface (the database connectors, file headers), internal implementation details (i.e. using STL algorithms for your implementation does not affect your interface, functors that are created for a simple purpose, utilities...)
With a very few exceptions, you are not allowed to add things to the std:; namespace. For classes like vector and string, you therefore have no option but to #include the relevant Standard header files.
Also, notice that string is not a class, but a typedef for basic_string<char>.
This won't help for vector or string, but it might be worth mentioning that there is a forward reference header for iostream, called iosfwd.
Standard containers often have additional default template parameters (allocators, etc.) so this will not work. For example, here's a snippet from GNU implementation:
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class vector : protected _Vector_base<_Tp, _Alloc>
{ ... };
This was something I was trying to do earlier too, but this is not possible due to templates.
Please see my question: Forward Declaration of a Base Class
As such headers don't change during your development it's not worth optimizing that anyway...
There is no simple obvious way to do it (as others have explained it very well).
However these headers should be seen as being part of the language (really!), so you can let them in your own headers without any problem, nobody will ever complain.
If your concern is compilation speed, I encourage you to use pre-compiled header instead and put these std headers in it (among other things). It will significantly increase your compilation speed.
Sorry the for the "real winner is the one who avoid the fight" kind of answer.
Just include the header in any file where you reference an STL collection.
As others have mentioned, there's not a way to reliably forward declare the STL classes, and even if you find one for your particular implementation, it will probably break if you use a different STL implementation.
If the compilation units don't instantiate the classes, it won't make your object files any bigger.
If string and vector are used only in signatures of non-public members of you class, you could use the PImpl idiom:
// MyClass.h
class MyClassImpl;
class MyClass{
public:
MyClass();
void MyMethod();
private:
MyClassImpl* m_impl;
};
// MyClassImpl.h
#include <vector>
#include <string>
#include <MyClass.h>
class MyClassImpl{
public:
MyClassImpl();
void MyMethod();
protected:
std::vector<std::string> StdMethod();
};
// MyClass.cpp
#include <MyClass.h>
#include <MyClassImpl.h>
void MyClass::MyMethod(){
m_impl->MyMethod();
}
You are always including vector and string in the header file, but only in the implementation part of your class; files including only MyClass.h will not be pulling in string and vector.
WARNING
Expect that doing this will cause uproar.
The language allows you to derive your own classes:
// MyKludges.h
#include <vector>
#include <string>
class KludgeIntVector : public std::vector<int> {
// ...
};
class KludgeDoubleVector : public std::vector<double> {
// ...
};
class KludgeString : public std::string {
// ...
};
Change your functions to return KludgeString and KludgeIntVector. Since these are no longer templates, you can forward declare them in your header files, and include MyKludges.h in your implementation files.
Strictly speaking, derived classes do not inherit base class constructors, destructors, assignment operators, and friends. You will need to provide (trivial) implementations of any that you're using.
// LotsOfFunctions.h
// Look, no includes! All forward declared!
class KludgeString;
// 10,000 functions that use neither strings nor vectors
// ...
void someFunction(KludgeString &);
// ...
// Another 10,000 functions that use neither strings nor vectors
// someFunction.cpp
// Implement someFunction in its own compilation unit
// <string> and <vector> arrive on the next line
#include "MyKludges.h"
#include "LotsOfFunctions.h"
void someFunction(KludgeString &k) { k.clear(); }
Maybe you would better use the pimpl idiom: it appears to me that you don't want to expose the implementation of your class to client code. If the vector and string objects are aggregated by value, the compiler needs to see their full declarations.
With the exception of adding overloads to std::swap (the only exception I can think of right now), you are generally not allowed to add anything to the std namespace. Even if it were allowed, the actual declaration for std::vector is a lot more complicated than the code in the OP. See Nikolai N Fetissov's answer for an example.
All that aside, you have the additional problem of what your class users are going to do with functions that return a std::vector or std::string. The C++ Standard section 3.10 says that functions returning such objects are returning rvalues, and rvalues must be of a complete type. In English, if your users want to do anything with those functions, they'll have to #include <vector> or <string> anyway. I think it would be easier to #include the headers for them in your .h file and be done with it.
I assume your objective here is to speed up compile times? Otherwise I'm not sure why you would want to remove them.
Another approach (not pretty but practical) is to use macro guards around the include itself.
e.g.
#ifndef STDLIB_STRING
#include <string>
#define STDLIB_STRING
#endif
Although this looks messy, on large codebases it does indeed increase the compile times. What we did is create a Visual Studio macro that will automatically generate the guards. We bind the macro to a key for easy coding. Then it just becomes a company coding standard (or habit).
We also do it for our own includes as well.
e.g.
#ifndef UTILITY_DATE_TIME_H
#include "Utility/DateTime.h"
#endif
Since we have Visual Studio helpers to auto-generate the guards when we create our own header files, we don't need the #define. The macro knows it's a internal include because we always use the
#include ""
format for our own includes and
#include <>
for external includes.
I know it doesn't look pretty but it did speed up our compile times on a largish codebase by over 1/2 hour (from memory).

Why should the "PIMPL" idiom be used? [duplicate]

This question already has answers here:
Is the PIMPL idiom really used in practice?
(12 answers)
Closed 8 years ago.
Backgrounder:
The PIMPL Idiom (Pointer to IMPLementation) is a technique for implementation hiding in which a public class wraps a structure or class that cannot be seen outside the library the public class is part of.
This hides internal implementation details and data from the user of the library.
When implementing this idiom why would you place the public methods on the pimpl class and not the public class since the public classes method implementations would be compiled into the library and the user only has the header file?
To illustrate, this code puts the Purr() implementation on the impl class and wraps it as well.
Why not implement Purr directly on the public class?
// header file:
class Cat {
private:
class CatImpl; // Not defined here
CatImpl *cat_; // Handle
public:
Cat(); // Constructor
~Cat(); // Destructor
// Other operations...
Purr();
};
// CPP file:
#include "cat.h"
class Cat::CatImpl {
Purr();
... // The actual implementation can be anything
};
Cat::Cat() {
cat_ = new CatImpl;
}
Cat::~Cat() {
delete cat_;
}
Cat::Purr(){ cat_->Purr(); }
CatImpl::Purr(){
printf("purrrrrr");
}
I think most people refer to this as the Handle Body idiom. See James Coplien's book Advanced C++ Programming Styles and Idioms. It's also known as the Cheshire Cat because of Lewis Caroll's character that fades away until only the grin remains.
The example code should be distributed across two sets of source files. Then only Cat.h is the file that is shipped with the product.
CatImpl.h is included by Cat.cpp and CatImpl.cpp contains the implementation for CatImpl::Purr(). This won't be visible to the public using your product.
Basically the idea is to hide as much as possible of the implementation from prying eyes.
This is most useful where you have a commercial product that is shipped as a series of libraries that are accessed via an API that the customer's code is compiled against and linked to.
We did this with the rewrite of IONA's Orbix 3.3 product in 2000.
As mentioned by others, using his technique completely decouples the implementation from the interface of the object. Then you won't have to recompile everything that uses Cat if you just want to change the implementation of Purr().
This technique is used in a methodology called design by contract.
Because you want Purr() to be able to use private members of CatImpl. Cat::Purr() would not be allowed such an access without a friend declaration.
Because you then don't mix responsibilities: one class implements, one class forwards.
For what is worth, it separates the implementation from the interface. This is usually not very important in small size projects. But, in large projects and libraries, it can be used to reduce the build times significantly.
Consider that the implementation of Cat may include many headers, may involve template meta-programming which takes time to compile on its own. Why should a user, who just wants to use the Cat have to include all that? Hence, all the necessary files are hidden using the pimpl idiom (hence the forward declaration of CatImpl), and using the interface does not force the user to include them.
I'm developing a library for nonlinear optimization (read "lots of nasty math"), which is implemented in templates, so most of the code is in headers. It takes about five minutes to compile (on a decent multi-core CPU), and just parsing the headers in an otherwise empty .cpp takes about a minute. So anyone using the library has to wait a couple of minutes every time they compile their code, which makes the development quite tedious. However, by hiding the implementation and the headers, one just includes a simple interface file, which compiles instantly.
It does not necessarily have anything to do with protecting the implementation from being copied by other companies - which wouldn't probably happen anyway, unless the inner workings of your algorithm can be guessed from the definitions of the member variables (if so, it is probably not very complicated and not worth protecting in the first place).
If your class uses the PIMPL idiom, you can avoid changing the header file on the public class.
This allows you to add/remove methods to the PIMPL class, without modifying the external class's header file. You can also add/remove #includes to the PIMPL too.
When you change the external class's header file, you have to recompile everything that #includes it (and if any of those are header files, you have to recompile everything that #includes them, and so on).
Typically, the only reference to a PIMPL class in the header for the owner class (Cat in this case) would be a forward declaration, as you have done here, because that can greatly reduce the dependencies.
For example, if your PIMPL class has ComplicatedClass as a member (and not just a pointer or reference to it) then you would need to have ComplicatedClass fully defined before its use. In practice, this means including file "ComplicatedClass.h" (which will also indirectly include anything ComplicatedClass depends on). This can lead to a single header fill pulling in lots and lots of stuff, which is bad for managing your dependencies (and your compile times).
When you use the PIMPL idiom, you only need to #include the stuff used in the public interface of your owner type (which would be Cat here). Which makes things better for people using your library, and means you don't need to worry about people depending on some internal part of your library - either by mistake, or because they want to do something you don't allow, so they #define private public before including your files.
If it's a simple class, there's usually isn't any reason to use a PIMPL, but for times when the types are quite big, it can be a big help (especially in avoiding long build times).
Well, I wouldn't use it. I have a better alternative:
File foo.h
class Foo {
public:
virtual ~Foo() { }
virtual void someMethod() = 0;
// This "replaces" the constructor
static Foo *create();
}
File foo.cpp
namespace {
class FooImpl: virtual public Foo {
public:
void someMethod() {
//....
}
};
}
Foo *Foo::create() {
return new FooImpl;
}
Does this pattern have a name?
As someone who is also a Python and Java programmer, I like this a lot more than the PIMPL idiom.
Placing the call to the impl->Purr inside the .cpp file means that in the future you could do something completely different without having to change the header file.
Maybe next year they discover a helper method they could have called instead and so they can change the code to call that directly and not use impl->Purr at all. (Yes, they could achieve the same thing by updating the actual impl::Purr method as well, but in that case you are stuck with an extra function call that achieves nothing but calling the next function in turn.)
It also means the header only has definitions and does not have any implementation which makes for a cleaner separation, which is the whole point of the idiom.
We use the PIMPL idiom in order to emulate aspect-oriented programming where pre, post and error aspects are called before and after the execution of a member function.
struct Omg{
void purr(){ cout<< "purr\n"; }
};
struct Lol{
Omg* omg;
/*...*/
void purr(){ try{ pre(); omg-> purr(); post(); }catch(...){ error(); } }
};
We also use a pointer-to-base class to share different aspects between many classes.
The drawback of this approach is that the library user has to take into account all the aspects that are going to be executed, but only sees his/her class. It requires browsing the documentation for any side effects.
I just implemented my first PIMPL class over the last couple of days. I used it to eliminate problems I was having, including file *winsock2.*h in Borland Builder. It seemed to be screwing up struct alignment and since I had socket things in the class private data, those problems were spreading to any .cpp file that included the header.
By using PIMPL, winsock2.h was included in only one .cpp file where I could put a lid on the problem and not worry that it would come back to bite me.
To answer the original question, the advantage I found in forwarding the calls to the PIMPL class was that the PIMPL class is the same as what your original class would have been before you pimpl'd it, plus your implementations aren't spread over two classes in some weird fashion. It's much clearer to implement the public members to simply forward to the PIMPL class.
Like Mr Nodet said, one class, one responsibility.
I don't know if this is a difference worth mentioning but...
Would it be possible to have the implementation in its own namespace and have a public wrapper / library namespace for the code the user sees:
catlib::Cat::Purr(){ cat_->Purr(); }
cat::Cat::Purr(){
printf("purrrrrr");
}
This way all library code can make use of the cat namespace and as the need to expose a class to the user arises a wrapper could be created in the catlib namespace.
I find it telling that, in spite of how well-known the PIMPL idiom is, I don't see it crop up very often in real life (e.g., in open source projects).
I often wonder if the "benefits" are overblown; yes, you can make some of your implementation details even more hidden, and yes, you can change your implementation without changing the header, but it's not obvious that these are big advantages in reality.
That is to say, it's not clear that there's any need for your implementation to be that well hidden, and perhaps it's quite rare that people really do change only the implementation; as soon as you need to add new methods, say, you need to change the header anyway.