为什么C ++ STL如此严重地基于模板? (而不是*接口*)
我的意思是,除了它的义务名称(标准模板库)...
C ++最初的目的是将OOP概念呈现给C语言。那就是:你可以根据它的类和类层次结构来告诉特定实体可以做什么以及不可以做什么(不管它是怎么做的)。 由于多重继承的问题,一些能力组合更难以描述,而C ++支持接口的概念有点笨拙(与java等相比),但它在那里(可能是改善)。
然后模板和STL一起发挥作用。 STL似乎采用了传统的OOP概念,并使用模板代替,将它们冲淡。
应该区分使用模板来概括类型本身与模板操作无关的类型(例如容器)时的情况。 有一个vector<int>
非常有意义。
然而,在许多其他情况下(迭代器和算法),模板类型应该遵循一个“概念”(Input Iterator,Forward Iterator等),其中概念的实际细节完全由模板的实现来定义函数/类,而不是与模板一起使用的类的类,这有点反OOP的用法。
例如,你可以告诉函数:
void MyFunc(ForwardIterator<...> *I);
更新:由于在原始问题中尚不清楚,因此ForwardIterator可以自行模板化以允许任何ForwardIterator类型。 相反,将ForwardIterator作为一个概念。
期望只有通过查看其定义才能获得Forward Iterator,您需要查看以下实现或文档:
template <typename Type> void MyFunc(Type *I);
我可以赞成使用模板的两个说法:编译代码可以通过为每个使用的类型定制编译模板而不是使用vtables来提高效率。 事实上,模板可以用于本机类型。
然而,我正在寻找更为深刻的理由,为什么放弃古典OOP来支持STL的模板化? (假设你读了那么多:P)
简短的答案是“因为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版本更好地实现这些目标?
至于为什么STL被纳入语言,导致STL发生了几件事。
首先,模板被添加到C ++中。 添加它们的原因与将泛型添加到.NET中的原因大致相同。 能够在不丢弃类型安全的情况下编写像“T型容器”这样的东西似乎是一个好主意。 当然,他们落实的实施要复杂得多,而且功能强大。
然后人们发现他们添加的模板机制比预期的更强大。 有人开始尝试使用模板来编写更通用的库。 一种受函数式编程的启发,一种使用C ++的所有新功能。
他将它提交给C ++语言委员会,他花了相当长的时间来适应它,因为它看起来很奇怪和不同,但最终意识到它比它们必须包含的传统OOP等价物更好。 所以他们对它进行了一些调整,并将其采用到标准库中。
这不是一种意识形态的选择,它不是“我们是否想成为面对对手”的政治选择,而是一个非常实用的选择。 他们对图书馆进行了评估,发现它工作得很好。
无论如何,你提到的赞成STL的原因都是绝对必要的。
C ++标准库必须是高效。 如果它比等效的手动C代码效率低,那么人们就不会使用它。 这会降低生产力,增加错误的可能性,总体来说只是一个坏主意。
STL 必须处理原始类型,因为原始类型是C语言中的全部,而且它们是这两种语言的主要部分。 如果STL没有与本地数组一起工作,那就没用了 。
你的问题有一个很强的假设,即OOP是“最好的”。 我很想听听为什么。 你问他们为什么“抛弃古典OOP”。 我想知道为什么他们应该坚持下去。 它有哪些优势?
我认为你所要问/抱怨的最直接的答案是这样的:假设C ++是一种OOP语言是一种错误的假设。
C ++是一种多范式语言。 它可以使用OOP原则进行编程,可以通过程序进行编程,通用编程(模板)以及使用C ++ 11(以前称为C ++ 0x),甚至可以对某些功能进行功能编程。
C ++的设计者认为这是一个优势,所以他们会争辩说,当通用编程更好地解决问题时,将C ++限制为纯粹的OOP语言,并且更一般地说,它会退步。
我的理解是,Stroustrup最初更喜欢“OOP风格”的容器设计,实际上并没有看到任何其他的方式来做到这一点。 Alexander Stepanov是STL的负责人,他的目标不包括“使其面向对象”:
这是基本点:算法是在代数结构上定义的。 我花了几年时间才意识到,你必须通过增加对常规公理的复杂性要求来扩展结构的概念。 ......我相信迭代器理论是计算机科学的核心,因为环或环的理论是数学的核心。 每次我看一个算法,我都会尝试找到一个定义它的结构。 所以我想要做的是一般性地描述算法。 这就是我喜欢做的事情。 我可以花一个月时间研究一个众所周知的算法,试图找到它的通用表示。 ...
至少对我而言,STL是编程的唯一可能方式。 它确实与C ++编程完全不同,因为它在大多数教科书中都有介绍。 但是,你看,我并没有试图用C ++编程,而是试图找到处理软件的正确方法。 ...
我有很多错误的开始。 例如,在我理解为什么这种机制存在根本性缺陷并且不应该使用之前,我花了数年的时间试图寻找继承和虚拟的用途。 我很高兴没人能看到所有的中间步骤 - 其中大部分都非常愚蠢。
(他解释了为什么继承和虚拟 - 又名面向对象的设计“在根本上有缺陷,不应该在面试的其余部分使用”)。
一旦Stepanov将他的图书馆提交给Stroustrup,Stroustrup和其他人经历了艰巨的努力,将其纳入ISO C ++标准(同一访谈):
Bjarne Stroustrup的支持至关重要。 Bjarne真的想要标准中的STL,如果Bjarne想要什么,他就会得到它。 ......他甚至强迫我在STL上做出改变,我永远不会为别人做出任何改变......他是我认识的最独立的人。 他把事情做完了。 他花了一段时间才明白STL是怎么回事,但是当他这样做的时候,他准备推动STL。 他还为STL做出了贡献,他坚持认为不止一种编程方式是有效的 - 即十多年来没有结束的声音和炒作,并且追求灵活性,效率,超载和类型安全性的组合使STL成为可能的模板。 我想很清楚地说明,Bjarne是我这一代的卓越语言设计师。
链接地址: http://www.djcxy.com/p/29793.html上一篇: Why is the C++ STL is so heavily based on templates? (and not on *interfaces*)