编译时多态性和运行时多态性

sky*_*oor 9 c++

我注意到某处多态只是指虚函数.但是,在某些地方它们包括函数重载和模板.后来,我发现有两个术语,编译时多态和运行时多态.真的吗?

我的问题是,当我们一般性地讨论多态性时,广泛接受的含义是什么?

jal*_*alf 13

是的,你是对的,在C++中有两种公认的多态性"类型".他们的意思几乎就是你认为的意思

动态多态性

是C#/ Java/OOP人通常简称为"多态".它本质上是子类化,要么从基类派生并覆盖一个或多个虚函数,要么实现接口.(在C++中通过覆盖属于抽象基类的虚函数来完成)

静态多态性

在编译时发生,可以认为是变形的变形.这里的想法很简单,尽管完全不相关,但在函数中可以使用不同的类型来表示相同的概念.举一个非常简单的例子,考虑一下

template <typename T>
T add(const T& lhs, const T& rhs) { return lhs + rhs; }
Run Code Online (Sandbox Code Playgroud)

如果这是动态多态,那么我们将定义add函数以将某种"IAddable"对象作为其参数.尽管实现了不同的实现,但是可以使用实现该接口(或从该基类派生)的任何对象,这为我们提供了多态行为.我们不关心哪种类型传递给我们,只要它实现某种"可以加在一起"的界面.但是,编译器实际上并不知道将哪种类型传递给函数.确切类型仅在运行时已知,因此这是动态多态.

但是,在这里,我们不要求您从任何东西派生,类型T只需要定义 +运算符.然后静态插入.所以在编译时,我们可以在任何有效类型之间切换,只要它们的行为相同(意味着它们定义了我们需要的成员)

这是多态的另一种形式.原则上,效果是相同的:该函数适用于我们感兴趣的概念的任何实现.我们不关心我们处理的对象是字符串,int,浮点数还是复数,只要它实现了"可以加在一起"的概念.

由于使用的类型是静态已知的(在编译时),因此称为静态多态.并且实现静态多态的方式是通过模板和函数重载.

但是,当C++程序员 只是说多态时,他们通常会引用动态/运行时多态.

(请注意,对于所有语言来说并不一定如此.函数式程序员在使用术语时通常意味着静态多态性 - 使用某种参数化类型定义泛型函数的能力,类似于模板)


Lau*_*ves 8

"多态"字面意思是"多种形式".不幸的是,这个术语在计算机科学中有点超载(请原谅双关语).

FOLDOC称,多态性是"克里斯托弗·斯特拉希(Christopher Strachey,1967)首先发现的概念,由欣德利和米尔纳开发,允许任何类型的列表."

一般来说,它是"一种编程语言特性,允许使用统一的接口处理不同数据类型的值",引用维基百科,它继续描述两种主要类型的多态:

参数多态是指将相同的代码应用于多种数据类型.面向对象编程社区中的大多数人将此称为"泛型编程"而不是多态.泛型(以及某种程度上的模板)适合此类别.

Ad-hoc多态性是指将不同的代码用于不同的数据类型.重载属于此类别,覆盖也是如此.这就是面向对象社区中的人们在说"多态"时通常所指的.(实际上,当他们使用术语"多态"时,许多意味着重写,而不是超载)

对于ad-hoc多态性,还存在实现代码的解析是在运行时(动态)还是在编译时(静态)发生的问题.方法重载通常是静态的,方法重写是动态的.这就是术语静态/编译时多态性动态/运行时多态性的来源.


Goz*_*Goz 5

通常人们指的是我的经验中的运行时多态性......


Eri*_*sen 5

当C++程序员说"多态"时,他很可能意味着子类型多态,这意味着"后期绑定"或"动态绑定"与虚函数.函数重载和泛型编程都是多态的实例,它们在编译时确实涉及静态绑定,因此它们可以统称为编译时多态.子类型多态性几乎总是被称为多态性,但该术语也可以指上述所有内容.