pimpl: Avoiding pointer to pointer with pimpl

烈酒焚心 提交于 2019-12-12 13:07:44

问题


In this question I asked "pimpl: shared_ptr or unique_ptr" I've been convinced that the proper usage of the pimpl idiom is to use a unique_ptr, not a shared_ptr. It should act to the user as if there is no pointer at all, whereas quite clearly the shared_ptr introduces aliasing upon copying, which definitely acts like a pointer.

So, lets say a user wants to create a shared_ptr to my pimpl object (say if they want actually want multiple aliases to it). For example:

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

That would result in a shared_ptr pointing to a unique_ptr pointing to my implementation.

It would be nice if I could achieve something like the following:

my_pimpl x; // (1)
shared_ptr<my_pimpl> p(new my_pimpl()); // (2) Pointer to pointer here.
x.f(); // (3)
p->f(); // (4)

but with somehow getting rid of the pointer to pointer, whilst still maintaining the implementation hiding of pimpl.

Any ideas how to achieve this (I'm happy to change the line (2) and obviously my_pimpl, but want lines (3) and (4) to stay the same).


回答1:


There are a number of possible approaches depending on your constraints.

1. Create your own shared_my_pimpl class

Create a class shared_my_pimpl which has the same interface as my_pimpl but internally uses a shared_ptr instead of a unique_ptr. Now create a class shared_ptr_my_pimpl which holds a shared_my_pimpl and has an operator-> which returns a pointer to the shared_my_pimpl, so that you get -> notation instead of . notation for member access. You can add a function make_shared_ptr_my_pimpl to make it look more like shared_ptr usage.

Disadvantages:

  1. The type of the object is not shared_ptr<x> but shared_ptr_my_pimpl; it's just pretending to be a shared_ptr.
  2. You can't get a my_pimpl* or my_pimpl& to the object; it's a different type which just behaves the same.

2. Derive from an interface

Create an interface my_pimpl_interface with all relevant functions pure virtual. Derive both my_pimpl and my_pimpl::impl (your pimpl implementation class) from this interface. Add a function make_shared_my_pimpl which returns a shared_ptr<my_pimpl_interface> to a my_pimpl::impl. You can now refer to both the plain object and the shared_ptr object as my_pimpl_interface&.

Disadvantages:

  1. By making all functions virtual you incur an extra indirection in calling them, which may have been what you were trying to avoid. Your standard my_pimpl object will also pay this overhead.



回答2:


You should use an interface for this purpose, because then the user of your class can choose whether they want to use shared_ptr or unique_ptr.



来源:https://stackoverflow.com/questions/5578487/pimpl-avoiding-pointer-to-pointer-with-pimpl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!