C++风格:可复制的句柄包装类
C++ Style: copyable handle wrapper classes
让封装共享句柄的类可复制是可以接受的C++风格吗?
我经常发现自己编写的类通过在类接口后面持有shared_ptr来隐藏一些粗糙的C库或操作系统资源的细节。例如
class window
{
public:
window() : m_handle(OsCreateWindow(), OsDestroyWindow) {}
void make_it_dance();
void paint_it_red();
private:
shared_ptr<OS_WINDOW_HANDLE> m_handle;
}
因为类是可复制的,并且shared_ptr
做了艰苦的工作,所以实例可以随意传递,不会有任何泄漏或被破坏两次。所以,从技术上讲,一切都很好。我已经做了很多年了。
但最近我开始怀疑这种风格是否真的很好。毕竟,当类实例被复制时,句柄末尾的对象不会被复制。让所有这些类都不可复制,让用户清楚地知道他们正在处理对同一对象的引用,这会更好吗?现代C++强调"基于价值",而实例之间共享后端资源似乎违背了这一原则。
然而,结果是,我的代码中有很大一部分会处理指针,即使它们是智能指针。这似乎是一种倒退。
我想我理解你的困境。我有一个相当愚蠢的建议。
由于您的问题不是函数性的,而是期望复制您的window
实例会创建,因此,如果将这样一个类命名为window_handle
而不是window
,不是更好吗?
这意味着它只是某个窗口的句柄,复制它不会创建新窗口或类似的东西,它只是复制一个句柄。
要强调的是,我建议你保留你的设计(对我来说这是一个很好的设计,似乎对你很有帮助),只需更改你的命名,就可以改变对代码更高层的期望。
就我个人而言,我不允许复制,并同意使用共享指针是一种倒退。我还要补充的是,每个"Window"实例都应该包含一个唯一的OS_Window_HANDLE。
您还可以使用MFC方法在对象之间传递句柄。MFC使用Attach和Detach方法,如下所示。。。
class Window
{
public:
void Attach (OS_WINDOW_HANDLE handle)
{
ASSERT(NULL == m_handle); // or you could destroy the existing handle
m_handle = handle;
}
OS_WINDOW_HANDLE Detach()
{
OS_WINDOW_HANDLE retVal = m_handle;
m_handle = NULL;
return retVal;
}
private:
// disable copy constructor and assignment
Window(const Window&);
Window& operator=(const Window&);
};
如果句柄指向的资源不需要复制(浅拷贝),请使用std::shared_ptr
。如果确实需要复制(深度复制),则应使用std::unique_ptr
。如果不需要进行复制,请使用std::unique_ptr
。
一个可能的答案(以及引发问题的情况)是,静默地共享支持对象会使类的用户很难确保对象在特定点"死"。例如,对象可能是网络连接,并且用户出于安全原因需要知道该连接已经关闭。
如果连接包装器是可复制的,并且在实例之间共享连接,那么用户必须研究实例可能流动的路径,以确保副本不会保存在意外的地方,并保持连接打开。
另一方面,如果包装器是不可复制的,那么只有一个实例可以确保是死的。引用仍然可以分发,但一旦原始包装器死了,用户就可以确定支持对象也死了。
如果用户希望拥有共享副本,他们总是可以再次使用shared_ptr恢复该副本。但这一次是他们的决定。
- 外壳包装器句柄/执行交互式命令管道C++ UNIX
- 如何为句柄类提供运算符 -> 的常量版本
- 改进 Windows 句柄上的 RAI 模板类?
- 模板化类的模板化成员的函数句柄
- C++中的句柄类
- 将C++类铸造到另一个类中以创建OpenCV轨迹条句柄
- 通过传递句柄减速器将 C++ 包装为 C#
- 通过 C++ 中的函数创建类的新句柄
- 禁止访问 C++ 中的基类句柄
- 模板类来关闭句柄和其他 WINAPI 的?
- 对DLL句柄类进行切片
- WNDCLASS和Window句柄在单独的或相同的类中
- 需要通过引用类传递Windows事件句柄的帮助
- C++风格:可复制的句柄包装类
- 无法在 MFC Windowless Activex 中获取 Cwnd 类的句柄?
- 如何添加句柄作为类成员,其中类用于堆模板
- 在类中包装Windows句柄
- 如何在没有窗口句柄的情况下修改窗口类
- 通过C API边界向C++类传递句柄
- Win句柄的API包装器类