代码之家  ›  专栏  ›  技术社区  ›  Tronic

用最少的代码实现PIMPL

  •  10
  • Tronic  · 技术社区  · 14 年前

    什么样的技巧可以用来最小化实现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 回复  |  直到 14 年前
        1
  •  5
  •   amit kumar    14 年前

    PIMPL的实现 Loki 也许是个好答案。也见 DDJ Article 对此。

        2
  •  1
  •   Matthieu M.    14 年前

    这是可能的,但是一个幼稚的实现不是您想要的。

    问题是,模板通常是内联的,简单的实现是:

    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 通常在头文件中是已知的(不是为了二进制兼容性,而是为了依赖关系管理)。如果 对象 未知,则无法实现 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++中的一个经典习语,增加了另一个间接用法: