在 C++ 中,您可以使用模板同时拥有通用容器和类型安全容器。但是在 C 中,如果你想要通用容器,你必须(afaik) use void*
,这意味着你失去了类型安全。要拥有类型安全的容器,您必须为要保存的每种类型的数据重新实现它们。
鉴于 C 遵循比 C++ 更多的程序员知道他在做什么的哲学,那么在 C 中更惯用的做法是:使用带有 的通用容器void*
,或者为每种类型的数据制作自定义容器?
在 C++ 中,您可以使用模板同时拥有通用容器和类型安全容器。但是在 C 中,如果你想要通用容器,你必须(afaik) use void*
,这意味着你失去了类型安全。要拥有类型安全的容器,您必须为要保存的每种类型的数据重新实现它们。
鉴于 C 遵循比 C++ 更多的程序员知道他在做什么的哲学,那么在 C 中更惯用的做法是:使用带有 的通用容器void*
,或者为每种类型的数据制作自定义容器?
我的目标是通用容器:
一旦你习惯了它,void *
当我不在乎它的类型时,你只会想到它的类型。就像Object
在 Java 中一样——很长一段时间以来,通用容器也没有类型安全性。
你只有一个地方可以改进。
你没有得到类型安全;但是随着类型安全容器的重复实现,您将面临复制和粘贴错误的风险。这也可能导致错误。
所以我快速搜索了一下,看看在 C 容器领域是否出现了任何新的聪明想法。
我找到了这个。这是对完整 C 容器库的一次相当彻底的尝试。
它传递要包含在void *
指针中的元素。没有尝试指定特定类型的结构。
为了类型安全,您可以为每个容器编写一个“包装器”宏,它定义了一个主机 if 内联函数,该函数环绕无类型版本并提供类型安全。希望它们会被编译器优化掉,但这并不总是可能的。而且宏会很丑。
我想这就是为什么更多(应用程序)程序是用 C++ 而不是 C 编写的原因之一。用 C 创建复杂抽象的能力是有限的。您可以这样做,但通常会牺牲其他方面,例如性能或可维护性(例如,查看 C GTK 程序)。
要创建一个在 C 中处理通用数据的类型,您可以使用 avoid*
来传递数据。为每种可能的类型定义新算法是不切实际的。
void*
作为成员使用并没有真正的好处(除非编译时间是最重要的),您始终可以void*
在适当的地方强制转换,然后在必要时对无类型数据块进行操作。
我已经在 C 中实现了这样的接口(例如,具有不同类型的命名字段的多个变体)。我倾向于拥有类型安全性,并且在这些实现中很少发现强制转换为void*
一件好事。
……再说一次,我花在写 c++ 上的时间比写 c 的时间要多 :)