正如 Bjarne Stroustrup 所指出的,“C++ 是一门多范式语言。”它支持许多不同的编程风格(范式),而面向对象编程只是其中之一。其他的还有结构化编程和泛型编程等。
正如 Thomas Becker 在这篇有趣的文章中所解释的,泛型编程与 OOP 之间存在一种张力。下面是该文章引用的 C++ 元老 Alexander Stepanov 对 OOP 的看法:
Let us start with a little trivia quiz. Who said the following things about object-oriented programming?
"I find OOP technically unsound."
"I find OOP philosophically unsound."
"I find OOP methodologically wrong."
"I have yet to see an interesting piece of code that comes from these OO people."
"I think that object orientedness is almost as much of a hoax as artificial intelligence."
All the quotes above are from an interview with Alexander Stepanov, the inventor of the STL and elder statesman of generic programming.
To have a concrete idea about the generics flexibility, let’s compare the implementation of a class calculating a tax in OOP and generic programming.让我们来探究这两种方法之间的一个重大差异,它也许能解释 Alexander Stepanov 对 OOP 方法的看法。为了说明这一点,让我们以一个基本的税额计算器为例。

CTaxCalculator 只与派生自 ICalculator 的类协作。我们必须继承 ICalculator 并重写一些虚方法,才能实现自己的算法。
相比之下,下面是泛型版 TaxCalculator 的示例:

CGenericTaxCalculator 类不局限于与某一特定种类的类协作;它可以与任何能够计算税额的类型协作,无论该类型属于什么样的类层次结构。
OOP 方法更像是一种“以‘是’为导向的方法”:继承被过度使用;在几乎所有 OOP 代码中,类 A 与类 B 协作的前提是 B是另一个类(无论是否抽象)的一种。
另一方面,在泛型方法中,类 A 与 B 协作的前提是 B拥有某些特定的方法和字段——无需继承某个特定的类。
这让泛型编程更自然、更灵活:它允许开发者采用“以‘有’为导向的方法”。OOP 由于继承产生的高耦合而更加僵化,它迫使开发者遵循“以‘是’为导向的方法”。
仔细想想:“以‘有’为导向的方法”才是更自然的方式。事实上,在现实世界中,我与一个拥有特定技能的人协作,而不管他出身于哪个家族。
泛型编程的灵活性使其成为现代 C++ 设计的首选,正如 Andrei Alexandrescu 所指出的:
Modern C++ Design defines and systematically uses 泛型组件 - highly flexible design artifacts that are mixable and matchable to obtain rich behaviors with a small, orthogonal body of code.他的论述中有三点特别有趣:
- 《现代 C++ 设计》定义并系统化地使用泛型组件。
- 高度灵活的设计。
- 用一套小巧、正交的代码体获得丰富的行为。
总而言之,泛型编程比 OOP 方法更自然、更灵活,也为编写高效代码提供了更多选择。
