Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hide implementation by using a pointer (Pimpl idiom)

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..

like image 273
emesx Avatar asked Nov 06 '12 17:11

emesx


2 Answers

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).

like image 91
Matthieu M. Avatar answered Oct 06 '22 03:10

Matthieu M.


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_; }
like image 21
Bart van Ingen Schenau Avatar answered Oct 06 '22 02:10

Bart van Ingen Schenau