Pimpl: 使用Pimpl避免指向指针的问题

3
在这个问题中,我问了"pimpl: shared_ptr or unique_ptr", 我已经被说服使用pimpl惯用语的正确方法是使用unique_ptr而不是shared_ptr。它应该对用户表现为没有指针,而很明显shared_ptr在复制时会引入别名,这绝对像指针一样作用。
所以,假设用户想要创建一个shared_ptr到我的pimpl对象(如果他们实际上想要多个别名)。例如:
shared_ptr<my_pimpl> p(new my_pimpl());

那将导致一个指向我的实现的unique_ptr的shared_ptr。
如果我能实现以下内容,那就太好了:
my_pimpl x; // (1)
shared_ptr<my_pimpl> p(new my_pimpl()); // (2) Pointer to pointer here.
x.f(); // (3)
p->f(); // (4)

不过,希望摆脱指向指针的某种方式,同时仍然保持pimpl的实现隐藏。

有任何想法如何实现这一点(我愿意更改第(2)行和显然my_pimpl,但希望第(3)和(4)行保持不变)。


“my_pimpl” 是公共类还是私有类? - Dennis Zickefoose
实际上,这并不重要。如果第3行有效,则第4行也有效,假设“shared_ptr”具有预期的语义。即使“my_pimpl”是“unique_ptr<Impl>”的typedef,operator->也可以很好地“钻取”到底层类型中。 - Dennis Zickefoose
2个回答

2

根据您的约束条件,有许多可能的方法。

1. 创建自己的shared_my_pimpl类

创建一个名为shared_my_pimpl的类,该类具有与my_pimpl相同的接口,但在内部使用shared_ptr而不是unique_ptr。现在创建一个名为shared_ptr_my_pimpl的类,它持有一个shared_my_pimpl并具有一个operator->,该运算符返回指向shared_my_pimpl的指针,以便您获得->标记而不是.标记进行成员访问。您可以添加一个名为make_shared_ptr_my_pimpl的函数,使其看起来更像shared_ptr用法。

缺点:

  1. 对象的类型不是shared_ptr<x>,而是shared_ptr_my_pimpl;它只是假装是一个shared_ptr
  2. 您无法获取指向对象的my_pimpl*my_pimpl&类型的指针;它是一种不同的类型,只是表现相同。

2. 从接口派生

创建一个名为my_pimpl_interface的接口,其中包含所有相关函数的纯虚拟。从此接口派生出my_pimplmy_pimpl::impl(您的pimpl实现类)。添加一个名为make_shared_my_pimpl的函数,该函数返回指向my_pimpl::implshared_ptr<my_pimpl_interface>。现在,您可以将普通对象和shared_ptr对象都表示为my_pimpl_interface&

缺点:

  1. 通过使所有函数虚拟,您会产生额外的间接调用,在调用它们时可能会遇到问题。您的标准my_pimpl对象也将支付这个开销。

0
你应该使用接口来实现这个目的,因为这样你类的用户可以选择使用 shared_ptr 还是 unique_ptr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接