小编典典

为什么 C++ STL 如此依赖模板?(而不是在 *interfaces* 上)

all

我的意思是,除了它的强制性名称(标准模板库)......

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);

我可以提出两个支持使用模板的主张:通过为每种使用的类型量身定制模板,而不是使用
vtables,可以使编译的代码更高效。以及模板可以与本机类型一起使用的事实。

但是,我正在寻找一个更深刻的原因,为什么要放弃经典的 OOP 来支持 STL 的模板化?(假设你读了那么远:P)


阅读 67

收藏
2022-06-14

共1个答案

小编典典

简短的回答是“因为 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”。我想知道他们为什么要坚持下去。它会有哪些优势?

2022-06-14