从C++谈多态

多态(Polymorphism)指的是一种相同的形式(名称和操作等)表现出不同行为的概念,多态的概念由Christopher Strachey于1967年[1]定义为两个分支:特设型多态(Ad-hoc polymorphism)和通用型多态(Universal polymorphism),此处的特设仅与通用相对,并非贬义的。特设型多态在之后又被细分为特设强制多态(Ad-hoc coercion polymorphism)及特设重载多态(Ad-hoc overloading polymorphism,有时候也简称为特设多态)两类,通用型多态也被细分为参数多态(Parametric polymorphism)及包含多态(Inclusion polymorphism,又称子类型多态 Subtyping polymorphism)。通常在 OOP 的语境下我们所指的多态都是包含多态,这同样也是 C++ 标准中[2]唯一提到的多态形式。

特设强制多态中的强制指的是隐式转换这样的语义操作,这使得期望某一类型的地方允许出现不同的类型而不会导致错误,提供的值将会转换到期望的类型,在C++中通常的表现为:

特设重载多态中的重载指的是相同的名称(以及操作等,如操作符重载)在提供不同类型的参数之时使用不同的实现,模板的特化同样可以看作特设重载多态,同样我们通过例子来展现此多态形式:

参数多态即借由隐式或显式的参数,使得相同名称的实体表现出不同行为,C++ 中的直接体现即是模板,体现此多态性质的模板可能生成一组函数、类、类型别名、变量及概念(Concept),这样的模板被分别称为函数模板、类模板、别名模板、变量模板及概念,在其他同样具有参数多态的语言中对应函数模板及类模板的概念多被称为泛型函数及泛型类,而对于别名模板、变量模板及概念几乎没有其他语言具有类似的概念:

包含多态是最常被提到的多态形式,也即子类型多态,注意子类型(Subtyping)与继承(Inheritance)并非等价的概念,子类型一般是用于表达接口的兼容性,即当我们说 B 是 A 的子类型之时,我们所说的是对于 A 的操作都可以对 B 进行,继承则倾向于表现实现的重用,即 B 重用 A 的操作来实现自己的操作,则 B 继承自 A [3]。但很不幸地由于太多语言混淆这两个概念,很少有人能正确地区分它们,包含多态在 C++ 及多数其他语言中以继承的方式体现:

引用:

[1] C. Strachey, Fundamental concepts in programming languages, Notes for the International Summer School in Computer Programming, Copenhagen (1967)

[2] ISO/IEC 14882:2017 [class.virtual]

[3] https://www.cmi.ac.in/~madhavan/courses/pl2006/lecturenotes/lecture-notes/node28.html

“从C++谈多态”的3个回复

  1. 此处的特设仅与通用相对,并非贬义的
    某种意义上还真是贬义的委婉说法……

    通用型多态也被细分为参数多态(Parametric polymorphism)及包含多态(Inclusion polymorphism,又称子类型多态 Subtyping polymorphism)

    这是[Strachey67]之后搞出来的,还是加点文献吧。

    强制指的是转换(包括隐式和显式的)
    这是错的,强制一直仅指隐式转换。

  2. 此处的特设仅与通用相对,并非贬义的

    某种意义上还真是贬义的委婉说法……

    通用型多态也被细分为参数多态(Parametric polymorphism)及包含多态(Inclusion polymorphism,又称子类型多态 Subtyping polymorphism)

    这是[Strachey67]之后搞出来的,还是加点文献吧。

    强制指的是转换(包括隐式和显式的)

    这是错的,强制一直仅指隐式转换。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注