3

在这个问题中,我问了“pimpl:shared_ptr 或 unique_ptr”,我确信 pimpl 习语的正确用法是使用 a unique_ptr,而不是 a shared_ptr。它应该对用户起作用,就好像根本没有指针一样,而很明显,shared_ptr在复制时引入了别名,这绝对像一个指针。

因此,假设用户想要为shared_ptr我的 pimpl 对象创建一个(假设他们是否真的想要多个别名)。例如:

shared_ptr<my_pimpl> p(new my_pimpl());

这将导致shared_ptr指向unique_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) 行保持不变)。

4

2 回答 2

2

根据您的限制,有许多可能的方法。

1. 创建自己的 shared_my_pimpl 类

创建一个shared_my_pimpl具有相同接口my_pimpl但内部使用 shared_ptr 而不是unique_ptr. 现在创建一个类shared_ptr_my_pimpl,该类包含 ashared_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_pimpland my_pimpl::impl(你的 pimpl 实现类)。添加一个make_shared_my_pimpl将 a 返回shared_ptr<my_pimpl_interface>到 a的函数my_pimpl::impl。您现在可以将普通对象和 shared_ptr 对象都称为my_pimpl_interface&.

缺点:

  1. 通过使所有函数虚拟化,您在调用它们时会产生额外的间接性,这可能是您试图避免的。您的标准my_pimpl对象也将支付此开销。
于 2011-04-07T11:43:53.813 回答
0

为此,您应该使用接口,因为您的类的用户可以选择是否要shared_ptr使用unique_ptr.

于 2011-04-07T13:53:55.973 回答