用最少量的代码实现pImpl

时间:2010-03-01 02:07:44

标签: c++ boost pimpl-idiom

可以使用哪种技巧来最小化实现pImpl类的工作量?

部首:

class Foo {
    struct Impl;
    boost::scoped_ptr<Impl> self;
public:
    Foo(int arg);
    ~Foo();
    // Public member functions go here
};

实现:

struct Foo::Impl {
    Impl(int arg): something(arg) {}
    // All data members and private functions go here
};

Foo::Foo(int arg): self(new Impl(arg)) {}
Foo::~Foo() {}

// Foo's public functions go here (and they refer to data as self->something)

如何使用Boost,可能继承,CRTP或其他技巧来避免尽可能多的样板代码?运行时性能不是问题。

2 个答案:

答案 0 :(得分:5)

Loki实施pimpl可能是一个很好的答案。另请参阅DDJ Article

答案 1 :(得分:1)

这是可能的,但是天真的实现并不是你想要的。

问题在于模板通常是内联的,天真的实现方式是:

template <class Object>
class Pimpl
{
public:
  explicit Pimpl(Object* obj): mObject(obj) {}
  ~Pimpl() { delete mObject; }

  // either deep copy or no copy
private:
  Object* mObject;
};

现在问题是你不希望在头文件中知道Object(不是为了二进制兼容性,而是为了依赖管理)。如果Object未知,则您无法直接实施DestructorCopy ConstructorAssignment Operator ...

然而问题远非无法解决! Boost确实为shared_ptr解决了这个问题。

这个想法是在构造函数中传递第二个项目,它将负责释放第一个项目的内存,并且将提供一个很好的默认实现。

当然,这是间接的。

namespace detail {
  template <class Object>
  struct Deleter { virtual void do(Object*) = 0; };
}

template <class Object>
class Pimpl
{
public:
  typedef detail::Deleter<Object> deleter_type;
  typedef boost::shared_ptr<deleter_type> deleter_pointer;

  Pimpl(std::auto_ptr<Object> obj, deleter_pointer del);
  ~Pimpl();
  Pimpl(const Pimpl&);
  Pimpl& operator(const Pimpl&);

private:
  Object* mObject;
  deleter_pointer mDeleter;
};

这是C ++中的经典习语,增加了另一层次的间接性:)