为什么 STL 如此依赖模板而不是继承?

新手上路,请多包涵

我的意思是,除了它的名字 _是标准模板库_(它演变成 C++ 标准库)。

C++ 最初将 OOP 概念引入 C。也就是说:您可以根据其类和类层次结构来判断特定实体可以做什么和不能做什么(不管它是如何做的)。由于多重继承的复杂性,以及 C++ 以某种笨拙的方式(与 java 等相比)支持仅接口继承这一事实,一些能力的组合更难以以这种方式描述,但它就在那里(并且可能是改进)。

然后模板与 STL 一起发挥作用。 STL 似乎采用了经典的 OOP 概念并将它们冲淡了,而是使用模板。

当模板用于泛化类型本身与模板的操作无关的情况(例如容器)时,应该区分这些情况。拥有 vector<int> 非常有意义。

然而,在许多其他情况下(迭代器和算法),模板化类型应该遵循一个“概念”(输入迭代器、前向迭代器等),其中概念的实际细节完全由模板的实现定义函数/类,而不是与模板一起使用的类型的类,这在某种程度上是对 OOP 的反用法。

例如,您可以告诉函数:

 void MyFunc(ForwardIterator<...> *I);

更新: 由于在原始问题中不清楚, ForwardIterator 可以自己模板化以允许任何 ForwardIterator 类型。相反的是将 ForwardIterator 作为一个概念。

仅通过查看其定义来期望 Forward Iterator,您需要查看以下实现或文档:

 template <typename Type> void MyFunc(Type *I);

我可以提出两个支持使用模板的主张: 1. 通过为每种使用的类型重新编译模板,而不是使用动态调度(主要通过 vtables),可以使编译的代码更高效。 2. 模板可以与原生类型一起使用。

然而,我正在寻找一个更深刻的理由来放弃经典的 OOP 以支持 STL 的模板化?

原文由 OB OB 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 648
2 个回答

简短的回答是“因为 C++ 已经向前发展了”。是的,早在 70 年代后期,Stroustrup 就打算创建具有 OOP 功能的升级 C,但那是很久以前的事了。到 1998 年语言标准化时,它不再是 OOP 语言。这是一种多范式语言。它当然对 OOP 代码有一些支持,但它也覆盖了图灵完备的模板语言,它允许编译时元编程,并且人们发现了泛型编程。突然之间,OOP 似乎并不那么重要了。当我们可以通过使用模板和通用编程提供的技术来编写更简单、更简洁 更高效的代码时,情况就不是这样了。

OOP 不是圣杯。这是一个可爱的想法,与 70 年代发明时的过程语言相比,这是一个相当大的改进。但老实说,这并不是它的全部。在许多情况下,它既笨拙又冗长,并且并没有真正促进可重用代码或模块化。

这就是今天 C++ 社区对泛型编程更感兴趣的原因,也是为什么 每个人 最终都开始意识到函数式编程也非常聪明的原因。 OOP 本身并不是一个漂亮的景象。

尝试绘制一个假设的“OOP-ified”STL 的依赖关系图。有多少班级必须相互了解?会有 很多 依赖。您是否可以只包含 vector 标头,而无需获得 iterator 甚至 iostream 被拉入? STL 使这很容易。向量知道它定义的迭代器类型,仅此而已。 STL 算法 _一无所知_。它们甚至不需要包含迭代器标头,即使它们都接受迭代器作为参数。那么哪个更模块化?

STL 可能不遵循 Java 定义的 OOP 规则,但它没有达到 OOP 的 目标 吗?不是实现了可重用、低耦合、模块化和封装吗?

它不是比 OOP-ified 版本 更好地 实现这些目标吗?

至于为什么 STL 被采用到语言中,发生了几件事导致了 STL。

首先,模板被添加到 C++ 中。添加它们的原因与将泛型添加到 .NET 中的原因大致相同。能够在不抛弃类型安全的情况下编写诸如“T 型容器”之类的东西似乎是个好主意。当然,他们确定的实现要复杂得多,功能强大得多。

然后人们发现他们添加的模板机制比预期的还要强大。有人开始尝试使用模板来编写更通用的库。一种受函数式编程的启发,另一种使用了 C++ 的所有新功能。

他将它介绍给 C++ 语言委员会,该委员会花了很长时间才习惯它,因为它看起来如此奇怪和不同,但最终意识到 _它比他们必须包含的传统 OOP 等效项更好_。因此他们对其进行了一些调整,并将其纳入标准库。

这不是意识形态的选择,也不是“我们要不要成为 OOP”的政治选择,而是非常务实的选择。他们评估了图书馆,发现它运作良好。

无论如何,您提到的支持 STL 的两个原因都是绝对必要的。

C++ 标准库 必须 高效。如果它的效率不如等效的手动 C 代码,那么人们就不会使用它。这会降低生产力,增加错误的可能性,并且总体上只是一个坏主意。

STL 必须 使用原始类型,因为原始类型是 C 中的全部内容,并且它们是两种语言的主要部分。如果 STL 不适用于本机数组,那将 毫无用处

您的问题强烈假设 OOP 是“最好的”。我很想知道为什么。你问他们为什么“放弃经典的 OOP”。我想知道他们为什么要坚持下去。它会有哪些优势?

原文由 jalf 发布,翻译遵循 CC BY-SA 4.0 许可协议

我认为您要问/抱怨的最直接的答案是:C++ 是 OOP 语言的假设是错误的假设。

C++ 是一种多范式语言。它可以使用 OOP 原则进行编程,可以按程序进行编程,可以通用(模板)进行编程,并且使用 C++11(以前称为 C++0x)甚至可以对某些东西进行功能编程。

C++ 的设计者认为这是一个优势,因此他们认为,当泛型编程可以更好地解决问题时,将 C++ 限制为像纯粹的 OOP 语言一样工作,嗯,更 _一般地说_,这将是一种倒退。

原文由 Tyler McHenry 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题