fbpx
维基百科

函数重载

函数重载(英語:function overloading)或方法重载,是某些编程语言(如 C++C#JavaSwiftKotlin 等)具有的一项特性,该特性允许创建多个具有不同实现的同名函数。对重载函数的调用会运行其适用于调用上下文的具体实现,即允许一个函数调用根据上下文执行不同的任务。

例如,doTask()doTask(object o) 是重载函数。调用后者,必须传入一个 object 作为参数,而调用前者时则不需要参数。一个常见的错误是在第二个函数中为 object 分配一个缺省值,这将会导致意义模糊的调用错误,因为编译器不知道使用这两种方法中的哪一种。

另一个例子是 Print(object o) 函数,它根据是打印文本还是照片来执行不同的操作。这两个不同的功能可以重载为 Print(text_object T); Print(image_object P)。如果我们为程序中将要“打印”的所有对象编写重载的打印函数,就不必担心 object 的类型,再次调用相应的函数,调用始终是:Print(something)

支持函数重载的语言 编辑

支持函数重载的语言包括但不限于以下几种:

函数重载规则 编辑

  • 多个函数定义使用相同的函数名称
  • 函数参数的数量或类型必须有区别

函数重载是静态多态的一种类别,其使用某种“最佳匹配”算法解析函数调用,通过找到形式参数类型与实际参数类型的最佳匹配来解析要调用的具体函数。该算法的细节因语言而异。

函数重载通常与静态类型编程语言(在函数调用中强制执行类型检查)有关。重载函数实际上只是一组具有相同名称的不同函数。具体调用使用哪个函数是在编译期决定的。

Java 中,函数重载也被称为编译时多态和静态多态。

函数重载不应与在运行时进行选择的多态形式混淆,例如通过虚函数而不是静态函数。

示例:C++ 中的函数重载

#include <iostream> int Volume(int s) { // 立方体的体积。  return s * s * s; } double Volume(double r, int h) { // 圆柱体的体积。  return 3.1415926 * r * r * static_cast<double>(h); } long Volume(long l, int b, int h) { // 长方体的体积。  return l * b * h; } int main() {  std::cout << Volume(10);  std::cout << Volume(2.5, 8);  std::cout << Volume(100l, 75, 15); } 

在上面的例子中,每个零件的体积是使用名为 Volume 的三个函数之一进行计算的,根据实际参数的不同数量和类型进行选择。

构造器重载 编辑

在某些面向对象编程语言中,用于创建对象实例的构造函数也可能被重载。在许多语言中,构造函数的名称是由类的名称预先确定的,因此似乎只能有一个构造函数。每当需要多个构造函数时,它们将会被实现为重载函数。在 C++ 中,缺省构造函数不带参数,使用其适当的缺省值实例化对象成员。例如,用 C++ 编写的餐厅账单对象的缺省构造函数可能会将小费设置为 15%:

Bill()  : tip(0.15), // 百分比  total(0.0) { } 

这样做的缺点是对于创建好的 Bill 对象,更改其值需要两步才能完成。下面显示了在主程序中对象的创建和对其值的更改:

Bill cafe; cafe.tip = 0.10; cafe.total = 4.00; 

通过重载构造函数,我们可以在创建对象的同时传递 tiptotal 这两个参数。这表现为带有两个参数的重载构造函数。这个重载的构造函数和我们之前使用的原始构造函数一样放置在类中。使用哪一个取决于创建新 Bill 对象时提供的参数数量(无,或两个):

Bill(double tip, double total)  : tip(tip),  total(total) { } 

现在,创建新 Bill 对象的函数可以将两个值传递给构造函数,一步到位设定好数据成员。下面显示了对象的创建和对其值的设定:

Bill cafe(0.10, 4.00); 

这对于提高程序效率和缩减代码长度很有用。

构造函数重载的另一个原因可能是强制执行强制性数据成员。在这个例子中,缺省构造函数被声明为 private 或 protected(或者最好是 C++11 起加入的 deleted),以使其无法从外部访问。对于上面的 Billtotal 可能是唯一的构造函数参数 – 因为 Bill 没有为 total 提供实用的缺省值 – 而 tip 的缺省值为 0.15

注意事项 编辑

两个问题与函数重载相互影响并使其复杂化:名称解析(因为作用域)和隐式类型转换

如果在一个作用域中声明了一个函数,然后在内部作用域中声明了另一个同名函数,则有两种正常的可能的重载行为:内部声明掩盖了外部声明(无论签名如何),或者内部声明和外部声明都包含在重载中,只有在签名匹配时,内部声明才会屏蔽外部声明。第一个取自 C++:“在 C++ 中,没有跨作用域的重载。”[5] 因此,要获得不同作用域中声明的函数的重载集,需要将外部作用域中的函数显式导入到内部作用域,使用 using 关键字。

隐式类型转换使函数重载复杂化,因为如果参数类型与重载函数之一的签名不完全匹配,但可以在类型转换后匹配,则解析取决于选择哪种类型转换。

这些能够以令人困惑的方式组合:例如,在内部作用域中声明的不精确匹配可以掩盖在外部作用域中声明的精确匹配。[5]

例如,有一个派生类,其重载函数带有一个 double 或一个 int,使用基类中带有 int 的函数,在 C++ 中可以这样写:

class B {  public:  void F(int i); }; class D : public B {  public:  using B::F;  void F(double d); }; 

如果不包含 using 关键字,会导致传递给派生类中 Fint 参数被转换成 double ,以匹配派生类中的函数,而不是基类中的函数;包含 using 导致派生类中的重载,以匹配基类中的函数。

附加说明 编辑

如果一个方法设计有过多的重载,开发者可能很难通过阅读代码来辨别正在调用哪个重载。如果某些重载参数的类型是其他可能参数的继承类型(例如“对象”),则尤其如此。IDE 可以执行重载解析并显示(或导航到)正确的重载。

基于类型的重载也会妨碍代码维护,其中代码更新可能会意外更改编译器选择的方法重载。[6]

另见 编辑

参考 编辑

  1. ^ . kotlinlang.org. [2021-09-13]. (原始内容存档于2022-05-16). 
  2. ^ . PostgreSQL Documentation. 2021-08-12 [2021-08-29]. (原始内容存档于2021-08-29) (英语). 
  3. ^ . docs.oracle.com. [2021-08-29]. (原始内容存档于2022-04-29) (英语). 
  4. ^ . nim-lang.org. [2021-09-13]. (原始内容存档于2021-06-15) (英语). 
  5. ^ 5.0 5.1 Stroustrup, Bjarne. . [2021-09-13]. (原始内容存档于2020-07-02).  引证错误:带有name属性“bjarne_faq”的<ref>标签用不同内容定义了多次
  6. ^ Bracha, Gilad. . Room 101. 3 September 2009 [2021-09-13]. (原始内容存档于2017-04-05). 

外部链接 编辑

  • Bertrand Meyer: Overloading vs Object Technology, in Journal of Object-Oriented Programming (JOOP), vol. 14, no. 4, October-November 2001, available online (页面存档备份,存于互联网档案馆

函数重载, 此條目需要擴充, 2012年7月2日, 请協助改善这篇條目, 更進一步的信息可能會在討論頁或扩充请求中找到, 请在擴充條目後將此模板移除, 英語, function, overloading, 或方法重载, 是某些编程语言, java, swift, kotlin, 具有的一项特性, 该特性允许创建多个具有不同实现的同名函数, 对重载函数的调用会运行其适用于调用上下文的具体实现, 即允许一个函数调用根据上下文执行不同的任务, 例如, dotask, dotask, object, 是重载函数, 调用后者. 此條目需要擴充 2012年7月2日 请協助改善这篇條目 更進一步的信息可能會在討論頁或扩充请求中找到 请在擴充條目後將此模板移除 函数重载 英語 function overloading 或方法重载 是某些编程语言 如 C C Java Swift Kotlin 等 具有的一项特性 该特性允许创建多个具有不同实现的同名函数 对重载函数的调用会运行其适用于调用上下文的具体实现 即允许一个函数调用根据上下文执行不同的任务 例如 doTask 和 doTask object o 是重载函数 调用后者 必须传入一个 object 作为参数 而调用前者时则不需要参数 一个常见的错误是在第二个函数中为 object 分配一个缺省值 这将会导致意义模糊的调用错误 因为编译器不知道使用这两种方法中的哪一种 另一个例子是 Print object o 函数 它根据是打印文本还是照片来执行不同的操作 这两个不同的功能可以重载为 Print text object T Print image object P 如果我们为程序中将要 打印 的所有对象编写重载的打印函数 就不必担心 object 的类型 再次调用相应的函数 调用始终是 Print something 目录 1 支持函数重载的语言 2 函数重载规则 3 构造器重载 4 注意事项 5 附加说明 6 另见 7 参考 8 外部链接支持函数重载的语言 编辑支持函数重载的语言包括但不限于以下几种 Apex C C Swift Fortran Kotlin 1 Java PostgreSQL 2 and PL SQL 3 Scala Wolfram Elixir Nim 4 函数重载规则 编辑多个函数定义使用相同的函数名称 函数参数的数量或类型必须有区别 函数重载是静态多态的一种类别 其使用某种 最佳匹配 算法解析函数调用 通过找到形式参数类型与实际参数类型的最佳匹配来解析要调用的具体函数 该算法的细节因语言而异 函数重载通常与静态类型编程语言 在函数调用中强制执行类型检查 有关 重载函数实际上只是一组具有相同名称的不同函数 具体调用使用哪个函数是在编译期决定的 在 Java 中 函数重载也被称为编译时多态和静态多态 函数重载不应与在运行时进行选择的多态形式混淆 例如通过虚函数而不是静态函数 示例 C 中的函数重载 include lt iostream gt int Volume int s 立方体的体积 return s s s double Volume double r int h 圆柱体的体积 return 3 1415926 r r static cast lt double gt h long Volume long l int b int h 长方体的体积 return l b h int main std cout lt lt Volume 10 std cout lt lt Volume 2 5 8 std cout lt lt Volume 100l 75 15 在上面的例子中 每个零件的体积是使用名为 Volume 的三个函数之一进行计算的 根据实际参数的不同数量和类型进行选择 构造器重载 编辑在某些面向对象的编程语言中 用于创建对象实例的构造函数也可能被重载 在许多语言中 构造函数的名称是由类的名称预先确定的 因此似乎只能有一个构造函数 每当需要多个构造函数时 它们将会被实现为重载函数 在 C 中 缺省构造函数不带参数 使用其适当的缺省值实例化对象成员 例如 用 C 编写的餐厅账单对象的缺省构造函数可能会将小费设置为 15 Bill tip 0 15 百分比 total 0 0 这样做的缺点是对于创建好的 Bill 对象 更改其值需要两步才能完成 下面显示了在主程序中对象的创建和对其值的更改 Bill cafe cafe tip 0 10 cafe total 4 00 通过重载构造函数 我们可以在创建对象的同时传递 tip 和 total 这两个参数 这表现为带有两个参数的重载构造函数 这个重载的构造函数和我们之前使用的原始构造函数一样放置在类中 使用哪一个取决于创建新 Bill 对象时提供的参数数量 无 或两个 Bill double tip double total tip tip total total 现在 创建新 Bill 对象的函数可以将两个值传递给构造函数 一步到位设定好数据成员 下面显示了对象的创建和对其值的设定 Bill cafe 0 10 4 00 这对于提高程序效率和缩减代码长度很有用 构造函数重载的另一个原因可能是强制执行强制性数据成员 在这个例子中 缺省构造函数被声明为 private 或 protected 或者最好是 C 11 起加入的 deleted 以使其无法从外部访问 对于上面的 Bill total 可能是唯一的构造函数参数 因为 Bill 没有为 total 提供实用的缺省值 而 tip 的缺省值为 0 15 注意事项 编辑两个问题与函数重载相互影响并使其复杂化 名称解析 因为作用域 和隐式类型转换 如果在一个作用域中声明了一个函数 然后在内部作用域中声明了另一个同名函数 则有两种正常的可能的重载行为 内部声明掩盖了外部声明 无论签名如何 或者内部声明和外部声明都包含在重载中 只有在签名匹配时 内部声明才会屏蔽外部声明 第一个取自 C 在 C 中 没有跨作用域的重载 5 因此 要获得不同作用域中声明的函数的重载集 需要将外部作用域中的函数显式导入到内部作用域 使用 using 关键字 隐式类型转换使函数重载复杂化 因为如果参数类型与重载函数之一的签名不完全匹配 但可以在类型转换后匹配 则解析取决于选择哪种类型转换 这些能够以令人困惑的方式组合 例如 在内部作用域中声明的不精确匹配可以掩盖在外部作用域中声明的精确匹配 5 例如 有一个派生类 其重载函数带有一个 double 或一个 int 使用基类中带有 int 的函数 在 C 中可以这样写 class B public void F int i class D public B public using B F void F double d 如果不包含 using 关键字 会导致传递给派生类中 F 的 int 参数被转换成 double 以匹配派生类中的函数 而不是基类中的函数 包含 using 导致派生类中的重载 以匹配基类中的函数 附加说明 编辑如果一个方法设计有过多的重载 开发者可能很难通过阅读代码来辨别正在调用哪个重载 如果某些重载参数的类型是其他可能参数的继承类型 例如 对象 则尤其如此 IDE 可以执行重载解析并显示 或导航到 正确的重载 基于类型的重载也会妨碍代码维护 其中代码更新可能会意外更改编译器选择的方法重载 6 另见 编辑构造器 函数 面向对象程序设计参考 编辑 Kotlin language specification kotlinlang org 2021 09 13 原始内容存档于2022 05 16 37 6 Function Overloading PostgreSQL Documentation 2021 08 12 2021 08 29 原始内容存档于2021 08 29 英语 Database PL SQL User s Guide and Reference docs oracle com 2021 08 29 原始内容存档于2022 04 29 英语 Nim Manual nim lang org 2021 09 13 原始内容存档于2021 06 15 英语 5 0 5 1 Stroustrup Bjarne Why doesn t overloading work for derived classes 2021 09 13 原始内容存档于2020 07 02 引证错误 带有name属性 bjarne faq 的 lt ref gt 标签用不同内容定义了多次 Bracha Gilad Systemic Overload Room 101 3 September 2009 2021 09 13 原始内容存档于2017 04 05 外部链接 编辑Bertrand Meyer Overloading vs Object Technology in Journal of Object Oriented Programming JOOP vol 14 no 4 October November 2001 available online 页面存档备份 存于互联网档案馆 取自 https zh wikipedia org w index php title 函数重载 amp oldid 71988231, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。