typedef'ing共享指针的最佳策略是什么?

Mar*_*arc 20 c++ boost typedef shared-ptr

我有一个关于使用typedef进行冗长模板的快速问题.关键点:我发现自己处于一种腌制状态 - 似乎没有一个将typedef放在除客户端函数本地之外的好地方.虽然有类似的SO问题(例如参见这里),但似乎没有人能够解决这个问题.请注意,这个问题并没有解决下面的typedef是否可取的问题 - 我试图简化出于说明目的.

与我一起工作时出现了我的问题boost::shared_ptr<T>.基本上,我想做以下事情:

#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<Widget> WidgetPtr;
Run Code Online (Sandbox Code Playgroud)

将此typedef放在Widget声明头中似乎很难看.这里似乎有两个注意事项:(i)如果Widget它本身没有在其成员中使用共享指针,我们添加了一个额外的include(因为我们无法转发声明boost::shared_ptr模板类 - 如果我是正确的我错误?)(ii)如果我们想在声明另一个类(称为该类Foo)期间使用此typedef,我们通过包括Widget.h而不是简单地向前声明Widget或包括WidgetFwd.h...... 来违反最佳实践...除非后者重复此类型的def .此外,boost::shared_ptr<Widget>在声明Widget自己的过程中输入deff似乎没有意义- 我们似乎在混合Widget声明,期待客户如何利用Widget 接口.

好吧,所以这很糟糕,但这更糟糕:如果我不尝试上面的某些组合,我最终会在客户端代码中出现重复的typedef,这会产生不一致(因此,可能是错误) - 整个点就是给定的Widget,WidgetPtrtypedef本身应该作为一种类型.示例:我们不想Foo使用WidgetPtr一个typedef boost::shared_ptr,而Bar使用WidgetPtr作为typedef std::auto_ptr.

另一种方法(以及我在网上讨论中提到的少数几种方法之一)是将typedef作为公共成员,Widget然后使用Widget::Ptr:

class Widget {
// ...
public:
     typedef boost::shared_ptr<Widget> Ptr;
};
Run Code Online (Sandbox Code Playgroud)

同样,我不喜欢这个,因为(i)它表明指针类型在某种程度上是类的成员,并且(ii)它导致一个不稳定的接口.更糟糕的是:因为我编写的每个类都可能指向使用智能指针,我最终会追逐想象中的客户端尾部.丑陋,丑陋,丑陋.

就目前而言,我已经从这个代码库中删除了typedef(因为它们导致严重的混淆,重复)并在选定的函数中重新引入它们.这里再次出现了使用不一致的问题,但并不是那么严重.

我能想到的唯一其他解决方案 - 我不确定这是否被认为是一种好的做法 - 将是一个实用程序头,其中放置了typedef,可能在他们自己的命名空间内.在这个标题中,我们将包括并完成它.

我错过了一些明显的东西,或者这简直太难了?

PS-道歉的长度; 我找不到一种更简单的方法来充分表达问题.

jpa*_*cek 7

此外,在声明Widget本身期间输入boost :: shared_ptr似乎没有意义 - 我们似乎将Widget的声明与对客户端如何使用Widget接口的预期相混合.

首先,这完全没有错 - 毕竟,客户端将如何(并且可以)使用接口的方式接口本身的一部分; 对于C++而言,不是垃圾收集,对象的内存管理是其界面的一个相当重要的部分.

所以有两种情况.在一种情况下,Widget预期它将通过共享指针使用.这意味着,例如.从窗口小部件获取的子窗口小部件返回为shared_ptrs,创建的每个窗口小部件都有它shared_ptr,依此类推.WidgetPtr在相同的标题中输入undef是完全合法的Widget.

在第二种情况下,Widgets期望被管理,例如.通过普通newdelete.客户可以shared_ptr在特殊情况下使用s,但没有说明例如.打印机对话例程不能auto_ptr代替使用.客户必须准备好,如果wptr是a shared_ptr,那条线

shared_ptr<Widget> w2(wptr->firstChild()->parent());
Run Code Online (Sandbox Code Playgroud)

导致灾难.

你的问题似乎表明后者是你的情况.恕我直言,你所做的就是好的.客户可以选择管理Widget对象的方式,只要它不影响其他客户端.


Mat*_* M. 6

我不喜欢一个规定使用特定智能指针的库,但如果有必要,我会容忍它.

如果你想强迫用户总是用a shared_ptr来操作一个小部件,这是不可能的,所以甚至不用费心去尝试.

另一方面,如果你有一个Widget返回a 的方法boost::shared_ptr<Widget>,那么提供一个(理智的)typedef可能会简化客户端代码.

因此,我会推广使用内部typedef:

class Widget
{
public:
  typedef boost::shared_ptr<Widget> Ptr;

  Ptr AccessFirstChild();
}; // class Widget
Run Code Online (Sandbox Code Playgroud)

在这种情况下,它是完全可以#include的必要的标题.


Ste*_*end 5

在我看来,你是在思考这个问题.shared_ptr<Widget>无论如何,每个想拥有a 的人都必须包含Widget头文件.把typedef(这是一个好主意imo)放在Widget.h100%的意义上.

  • @Steve汤森:Widget`的`一个简单的向前声明,就足以操纵'的Widgets shared_ptr`,只要你不要试图Widget`的`接入方式,显然. (5认同)