Hide implementation by using a pointer (Pimpl idiom) - c++

Is it somehow possible, to accomplish the following:
x.hpp - this file is included by many other classes
class x_impl; //forward declare
class x {
public:
//methods...
private:
x_impl* impl_;
};
x.cpp - the implementation
#include <conrete_x>
typedef concrete_x x_impl; //obviously this doesn't work
//implementation of methods...
So basically, I want the users to include the file x.hpp, but be unaware of the conrete_x.hpp header.
Since I can use concrete_x only by a pointer and it appears only as a private data member, a forward declaration should be enough for the compiler to know how much space to prepare for it. It looks quite like the well-known "pimpl idiom".
Can you help me with this?
PS. I don't want to use a void* and cast it around..

Actually, it's even possible to completely hide from the user:
// Foo.hpp
class Foo {
public:
//...
private:
struct Impl;
Impl* _impl;
};
// Foo.cpp
struct Foo::Impl {
// stuff
};
I would just like to remind you that:
you will need to write a proper destructor
and thus you will also need a proper copy constructor, copy assignment operator, move constructor and move assignment operator
There are ways to automate PIMPL, at the cost of some black magic (similar to what std::shared_ptr does).

As an alternative to the answer from #Angew, if the name concrete_x should not be made known to users of class x, you could do this:
in x.hpp
class x_impl;
class x {
public:
x();
~x();
//methods...
private:
x_impl* impl_;
};
in x.cpp
#include <concrete_x>
class x_impl : public concrete_x { };
x:x() : impl_(new x_impl) {}
x:~x() { delete impl_; }

This will only work when the forward declaration declares the actual name of the class. So either change x.hpp to:
class concrete_x;
class x {
public:
//methods...
private:
concrete_x* impl_;
};
or use the name x_impl for the class defined in the header <concrete_x>.

That's what interfaces are for. Define an interface (pure virtual class) in your shared header file and give it to users. Inherit your concrete class from the interface and put it in the non-shared header file. Implement the concrete class in the cpp file (you can even define the concrete class inside the cpp).

Related

Hiding implementation of members owned by PImpl-objects

I have a class which I want to create an interface for without showing any of the implementation (not because it's closed source, but because of a lot of unnecessary headers such as OpenGL coming with it), let's call that class Foo. I know this is commonly done through either the PImpl-idiom or virtual interfaces, and I've implemented the PImpl-idiom for that class.
However, this class has public functions which returns other classes that are also including those headers, so obviously I can't return those objects as-is as that'd require me to include headers I don't want to include in Foo.h. However, these classes are used internally within the library a lot, and thus I don't want to implement them with PImpl as that'd introduce a lot of overhead (they're used a lot within a 3D renderer's code). Let's call one of them Bar:
Foo.h:
#include "Bar.h"
class Foo
{
private:
class impl;
std::unique_ptr<impl> m_pimpl;
public:
Foo();
Bar& get_bar();
};
Foo.cpp:
#include "Foo.h"
class Foo::impl {
private:
Bar m_bar;
public:
Bar& get_bar();
};
Foo::Foo() : m_pimpl{std::make_unique<impl>()}
{ }
Bar& Foo::get_bar() {
return m_pimpl->get_bar();
}
For this to work I need to #include "Bar.h", but Bar.h might include headers I want to hide. This leaves me with the option to make Bar use the PImpl-idiom as well, but I don't want that overhead for Bar because Bar is used a lot internally within Foo. However, I figured a way to solve this, but I'm not very sure about it as I haven't seen it used anywhere before:
Using PImpl without an owning pointer/reference to simply wrap a class and create a interface for it. This way the overhead only applies when outside of Foo, but internally it'll still use the non-wrapped class.
For example, let's say PBar is wrapping Bar:
PBar.h:
class Bar;
class PBar {
private:
Bar &m_bar;
public:
explicit PBar(Bar &bar);
void do_stuff();
};
PBar.cpp:
#include "PBar.h"
#include "../impl/Bar.h" // This is the actual Bar implementation
PBar::PBar(Bar &bar) : m_bar(bar) {
}
void PBar::do_stuff() {
m_bar.do_stuff();
}
And Foo instantiates PBar on creation with a reference to the actual Bar inside the object:
Foo.h
#include "PBar.h"
class Foo
{
private:
class impl;
std::unique_ptr<impl> m_pimpl;
PBar m_bar;
public:
Foo();
PBar& get_bar() { return m_bar; }
};
Foo.cpp:
class Foo::impl {
private:
Bar m_bar;
public:
Bar& get_bar();
};
Foo::Foo() : m_pimpl{std::make_unique<impl>()},
m_bar(impl->get_bar())
{ }
Is this pattern ever used? Are there any other ways I can solve this problem? It's more or less the same principle as PImpl, but is there anything bad about it I haven't yet thought about? It definitely feels even less clean, but I can't see how this could be done in any other way.
Also, I want neither PBar or Bar to be constructable outside of Foo, so that's not a problem.
Thanks!
You cannot (should not) change the object referenced by a reference member: how do you do here: Foo a,b; a=b; (supposing you initialize a non null unique_ptr). This is easily corrected replacing the reference by a pointer.
This look like a good idea, what you do is caching a dereferencement. But you are loosing some efficiency of the pimpl idiom and you are doubling the size of Foo.
Have you thought in making the class impl standard layout and putting Bar at a known offset inside impl:
Foo.h
constexpr auto impl_bar_offset = 8;
//...
class Foo{
private:
class impl;
std::unique_ptr<impl> m_impl;
public:
bar& get_bar(){
assert(m_impl);
return *reinterpret_cast<bar*>(
reinterpret_cast<unsigned char*>(m_impl.get())+impl_bar_offset);
}
};
Foo.cpp
class impl{
long a_long;
bar a_bar;
//...
};
static_assert(impl_bar_offset==offsetof(impl,a_bar));

Friend member function without class declaration

There is probably a really easy fix for this but it's boggling me currently. So, I'm writing C++ classes to the effect of:
Header.h:
#pragma once
//...
class arrayObj
{
private:
// some variables...
public:
//constructor, destructor, getters, etc...
friend void objManager::foo();
};
//...
class objManager
{
private:
//...
std::vector<std::shared_ptr<arrayObj>> array;
public:
void foo();
//other methods...
};
Now, as-is, my compiler will not find the class declaration of objManager (or the member function) declared for the friend inclusion. However, with the objManager declaration placed prior to the arrayObj, the arrayObj is no longer declared for the internal vector of shared pointers. Is there any way to forward declare objManager in this instance or otherwise solve this issue without dismantling the objManager into separate classes?
You need to forward-declare arrayObj, then put the full definition of the objManager, and then finally the definition of arrayObj:
class arrayObj;
class objManager {
std::vector<std::shared_ptr<arrayObj>> array; // OK, fwd-declare is fine for this
public:
void foo();
// etc.
};
class arrayObj {
public:
friend void objManager::foo();
// etc.
};
In order to declare a friend, that method has to already have been seen, so it has to go first. The forward declaration is a consequence of the vector.

Avoiding declaring private functions in class header files (C++)

(In C++) I have a class whose structure is declared in a header file. That header file is included in lots of source files, such that when I edit it I need to recompile lots of files.
The class has a set of private functions which are only called in one source file. Currently they are declared in the class structure in the header file. When I add a new function of this type, or edit the arguments, it therefore causes recompilation of lots of files. I would like to declare the functions somewhere else, such that only the file that defines and calls them is recompiled (to save time). They still need to be able to access the internal class variables, though.
How can I achieve this?
Use the pImpl idiom - Your visible class keeps a pointer to the real class and forwards calls to public member functions.
EDIT: In response to comments
// Foo.h:
class FooImpl; // Do *not* include FooImpl.h
class Foo {
public:
Foo();
~Foo();
//.. also need copy ctor and op=
int bar();
private:
FooImpl * Impl;
};
// FooImpl.h:
class FooImpl {
public:
int bar() { return Bar; }
private:
int Bar;
};
// Foo.cpp:
#include "FooImpl.h"
Foo::Foo() { Impl = new FooImpl(); }
Foo::~Foo() { delete Impl; }
int Foo::bar() { return Impl->bar(); }
Keep the actual implementation of your class in FooImpl - Foo should have copies of the public members of FooImpl and simply forward calls to these. All users will include only "Foo.h" - you can change all the private details of FooImpl without the users of Foo seeing any changes.
There is no way to declare member functions of a class outside the main class declaration. So, if you want to declare, outside of the class in question, functions that can access member variables of a particular instance of the class, then I see no alternative but to pass that instance to the function. Furthermore, if you want the functions to be able to access the private and protected variables you will need to put them in a new class and make the original class a friend of that. E.g.
header.h:
class FooImpl;
class Foo {
public:
int bar();
friend class FooImpl;
private:
int var;
}
impl.cpp:
#include "header.h"
class FooImpl {
public:
int bar(Foo &);
}
int FooImpl::bar(Foo &foo) {
return foo.var;
}
int Foo::bar() {
return FooImpl::bar(*this);
}
Are you looking for Compiler Firewall, a.k.a. PIMPL?
Create an abstract base class which contains only the public functions and reference this in your headers. Create your real class as an implementation somewhere else. Only source files which need to create your class need to see the implementation class header.

How to omit private non-virtual methods from class definition?

Lets say I have something like the following:
a.hpp:
class B;
class A
{
private:
std::unique_ptr<B> b_;
}
a.cpp:
#include <something_complicated.hpp>
struct B
{
something_complicated x;
}
something_complicated& A::get_complicated() { return b_->x; }
Unfortunately, in this case, a.cpp will fall to compile because "get_complicated()" is not a method of A.
So, we can try this:
a.hpp:
class B;
class A
{
private:
std::unique_ptr<B> b_;
something_complicated& A::get_complicated();
}
But then a.hpp fails to compile because something_complicated isn't defined.
We could forward declare something_complicated if it is a class, but it's probably a typedef, so that is out.
The only way I can think of doing this without making b_ public nor including something_complicated.hpp in a.hpp is the following:
a.cpp:
#include <something_complicated.hpp>
struct B
{
something_complicated x;
}
#define get_complicated ((b_->x))
Surely I don't have to define a macro to get around this issue? Any alternatives?
The easiest solution is probably to wrap a reference to the complicated type in a class, forward declare that in a.hpp, and define it in something_complicated.hpp.
a.hpp:
class B;
class complicated_ref;
class A
{
public:
complicated_ref get_complicated();
private:
std::unique_ptr<B> b_;
};
something_complicated.hpp:
// ... complicated definitions ...
typedef whatever something_complicated;
struct complicated_ref
{
complicated_ref(something_complicated & thing) : ref(thing) {}
something_complicated & ref;
};
Now a.cpp and anything that needs to use the complicated type must include it's header, but anything that just wants to use class A does not need to.
This is assuming that there's a good reason for some clients of A to access the complicated thing, but for B to be inaccessible to everyone. It would be simpler still to allow access to B when required, and get to the complicated thing through that.
I am afraid there is a misunderstand on what belong to the class, and what does not.
Not all methods that act on the internals of the class should be class methods, after all, we have friend functions already. I know that many people declare the helper methods as private functions, however doing so introduces needless dependencies (compile-time) and a visibility issue with friends.
When dealing with PIMPL, I tend not to use private functions. Instead, the choice is:
Making Impl (B in your case) a true class, with its own validation logic and true API
Using static free functions (or functions declared in an anonymous namespace)
Both are good, and use whichever seems most appropriate. Namely:
methods: when dealing with validation issues
free functions: for computing that can be expressed in terms of the aforementionned methods
It is deliberate on my part to search to have as few methods as possible, because those are the only ones that can screw up my class invariants, and the less they are the more confident I can be that the invariants will be maintained.
In your case, it's up to you to decide which approach suits you best.
In Action:
a.cpp
#include <something_complicated.hpp>
struct B
{
something_complicated x;
}
static something_complicated& get_complicated(B& b) { return b_.x; }
// or anonymous namespace instead
namespace {
something_complicated& get_complicated(B& b) { return b_.x; }
}
Not so different from what you had, eh ?
Note: I prefer static functions to anonymous namespaces because it's more obvious when reading. Namespaces introduce scopes, and scope are not glanced easily when sifting through a file. Your mileage may vary, both offer identical functionality (for functions).
Just avoid referring to something_complicated in a.hpp.
One solution is to replace the member function get_complicated with a free function, or a static method of another class.
.h:
class A_impl_base {
A_impl_base() {}
friend class A_impl; // all instances of A_impl_base are A_impl
}; // this stub class is the only wart the user sees
class A
{
private:
std::unique_ptr< A_impl_base > b_; // this is not a wart, it's a pimpl
friend class A_impl;
}
.cpp:
class A_impl : A_impl_base {
static A_impl &get( A &obj ) { return * obj.b_; }
static A_impl const &get( A const &obj ) { return * obj.b_; }
};
What's wrong with:
a.hpp:
class B;
class A
{
private:
std::unique_ptr<B> b_;
public:
B& get_B();
}
If your clients want to get something complicated out of B, then let them #include <something_complicated.hpp>.
We could forward declare something_complicated if it is a class, but it's probably a typedef, so that is out.
This is exactly what you have to do. And I don't see how being a typedef rules out a forward declaration.
If you control something_complicated.hpp you could do what the standard library does: Create a something_complicated_fwd.hpp that has appropriate forward declarations, including the types that may or may not be typedefs.

Is it possible not to include a class variable in a class header file?

I want to hide an implementation in implementation file. If the object is not public, I don't want the object's header to leak everywhere my class is used.
Suppose I have header file A.h for my class A:
#include "Foo.h"
class A{
private:
Foo foo;
public:
do_stuff();
};
Now wherever I would include A.h, Foo.h also would be included. But I have no use for class Foo anywhere outside of class A. I would rather not have this #include "Foo.h" line. Is there any way to move the declaration of 'foo' variable inside the implementation A.cpp?
I suspect one possible solution involves adding a layer of abstract class (interface analogy). Is it the best solution?
Thank you.
Use a pointer to Foo and allocate it dynamically, rather than using a member object. Then you only need to include Foo.h in A.cpp.
class Foo;
class A{
private:
Foo* foo;
public:
do_stuff();
}
David's got the right answer. I'll refer to this article for a little more treatment on this kind of "opaque pointer" trick, as you can get more elaborate with it, depending on your needs:
http://en.wikipedia.org/wiki/Opaque_pointer
Also, it's a good idea to use shared_ptr types for this purpose instead of raw pointers like the sample. This will take care of cleaning up resources for you automatically, once the last reference to Foo goes out of scope.
Yes. Choose yer poison!
Option 1. Forward declaration in interface.
class A {
private:
class Foo;
Foo* foo;
};
Option 2. ABC.
// A.hpp
class A {
public: virtual void do_stuff() = 0;
};
// A.cpp
class A_impl : public A {
class Foo { /*etc*/ };
Foo foo;
void do_stuff (){...}
};
Option 3. Private is private. It's "hidden" as far as the public API goes, which is all that matters:
class A {
private:
class Foo {
...
};
private_::Foo foo;
public:
do_stuff();
};
Option 4. Just put the declaration in a "non-public" namespace.i.e., omit it from documentation and name it something to frighten away prying eyes:
namespace private_ {
class Foo {
...
};
}
class A {
private:
private_::Foo foo;
public:
do_stuff();
};