3

我的库中有一个类,我想向用户公开。我不想公开整个类,因为我可能想稍后进行二进制不兼容的更改。我对以下哪种方法最好感到困惑。

情况1:

struct Impl1;
struct Handle1
{
  // The definition will not be inline and will be defined in a C file
  // Showing here for simplicity
  void interface()
  {
    static_cast<Impl1*>(this)->interface();
  }
}

struct Impl1 : public Handle1
{
  void interface(){ /* Do ***actual*** work */ }
  private:
  int _data; // And other private data
};

案例二:

struct Impl2
struct Handle2
{
  // Constructor/destructor to manage impl
  void interface() // Will not be inline as above.
  {
    _impl->interface();
  }
  private:
  Impl2* _impl;
}

struct Impl2
{
  void interface(){ /* Do ***actual*** work */ }
  private:
  int _data; // And other private data
};

Handle类仅用于公开功能。它们将仅在库内创建和管理。继承只是为了抽象实现细节。不会有多个/不同的impl类。在性能方面,我认为两者都是相同的。是吗?我正在考虑采用案例 1方法。有什么问题需要注意吗?

4

1 回答 1

2

您的第二种方法看起来非常像编译防火墙习语(有时称为PIMPL习语)。

唯一的区别是在编译防火墙惯用语中,实现类通常(但不总是)定义为成员。不要忘记构造函数(分配 Impl)和析构函数(释放 Impl)。连同复制构造函数和赋值运算符。

第一种方法也有效,但它需要工厂函数来创建对象。在我使用的时候,我只是把所有的函数都做成了Handle纯虚拟的,让客户端代码直接调用。

在这种情况下,由于客户端代码实际上有指向您的对象的指针(在编译防火墙的惯用语中,唯一​​的指针在Handle类本身中),客户端将不得不担心内存管理;如果没有循环是可能的,这是一种shared_ptr很有意义的情况。(例如,工厂函数可以返回一个 shared_ptr,而客户端代码可能永远不会看到原始指针。)

于 2012-09-28T11:01:40.373 回答