【发布时间】:2016-06-25 17:38:05
【问题描述】:
假设我正在构建一个链表(实际的数据结构完全不同,但链表足以解决问题),其节点看起来像
template <typename T>
struct node
{
struct node<T> *next;
T data;
};
对于我的数据结构,我有很多返回类型为struct node * 的函数,我希望用户将此类型视为不透明的。在链表示例中,这样的函数可以是例如get_next(struct node<T> *n) 或insert_after(struct node<T> *x, struct node<T> *y)。只有极少数功能,即分配nodes 或获取/设置其data 字段的功能,需要了解有关T 的任何信息。
有没有更好的方法来“忽略T”并让用户只与typedef struct node * opaque_handle 之类的东西进行交互,以实现那些不必关心T 的功能?我的直觉反应来自 C,只是在void* 之间进行转换,但这听起来不太优雅。
编辑: CygnusX1 的comment 让我相信,我要求类型系统提供太多保证,同时我试图规避太多这些保证。我将退回到让T 成为void *,但会以强制转换和间接为代价。
【问题讨论】:
-
也许听起来不太优雅,但它已被广泛使用。例如阅读pimpl。在公共标头中有一个前向声明
struct T,并在struct node中使用T*(在这种情况下不需要是模板) -
是否有特殊需要以公开
node<T>类型的方式设计您的数据结构?为什么不按照标准中的其他容器建模(用户界面函数返回T而不是node<T>)? -
您可能想看看STL 集合是如何处理这个问题的。它们实际上并没有让最终用户访问实现结构,例如
node。他们的接口包含一个可以被最终用户理解的抽象类型,如iteratorvalue_typereference等等。 -
@user2296177:我的意思是完全避免暴露
node<T>(对于几乎所有功能)。我想要typedef struct node<T> * handle_t的东西,并且大多数函数都接受并返回handle_t。 -
@gspr 问题是你根本不需要暴露
node<T>。从用户的 POV,您的数据结构函数返回T's。内存管理应该由数据结构或基类在内部完成。就像@WF 建议的那样,只需查看其中一个标准容器即可在界面上获得灵感。
标签: c++ templates opaque-pointers