10

可以使用什么样的技巧来最小化实现 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 或其他技巧来避免尽可能多的样板代码?运行时性能不是问题。

4

2 回答 2

5

Loki的 pimpl 实现可能是一个很好的答案。另请参阅有关此的DDJ 文章

于 2010-03-01T08:28:15.753 回答
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不知道,那么你不能实现Destructor,Copy Constructor并且Assignment 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++ 中的经典习语,再增加一层间接性 :)

于 2010-03-01T09:10:15.763 回答