函数重载
函数重载(英語:function overloading)或方法重载,是某些编程语言(如 C++、C#、Java、Swift、Kotlin 等)的特性,允许创建多个具有不同实现的同名函数。对重载函数的调用会运行其适用于调用上下文的具体实现,即允许一个函数调用根据上下文执行不同的任务。 例如, 另一个例子是 支持函数重载的语言支持函数重载的语言包括但不限于以下几种: 函数重载规则
函数重载是静态多态的一种类别,其使用某种“最佳匹配”算法解析函数调用,通过找到形式参数类型与实际参数类型的最佳匹配来解析要调用的具体函数。该算法的细节因语言而异。 函数重载通常与静态类型编程语言(在函数调用中强制执行类型检查)有关。重载函数实际上只是一组具有相同名称的不同函数。具体调用使用哪个函数是在编译期决定的。 在 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);
}
在上面的例子中,每个零件的体积是使用名为 构造器重载在某些面向对象的编程语言中,用于创建对象实例的构造函数也可能被重载。在许多语言中,构造函数的名称是由类的名称预先确定的,因此似乎只能有一个构造函数。每当需要多个构造函数时,它们将会被实现为重载函数。在 C++ 中,缺省构造函数不带参数,使用其适当的缺省值实例化对象成员。例如,用 C++ 编写的餐厅账单对象的缺省构造函数可能会将小费设置为 15%: Bill()
: tip(0.15), // 百分比
total(0.0)
{ }
这样做的缺点是对于创建好的 Bill cafe;
cafe.tip = 0.10;
cafe.total = 4.00;
通过重载构造函数,我们可以在创建对象的同时传递 Bill(double tip, double total)
: tip(tip),
total(total)
{ }
现在,创建新 Bill cafe(0.10, 4.00);
这对于提高程序效率和缩减代码长度很有用。 构造函数重载的另一个原因可能是强制执行强制性数据成员。在这个例子中,缺省构造函数被声明为 private 或 protected(或者最好是 C++11 起加入的 deleted),以使其无法从外部访问。对于上面的 注意事项两个问题与函数重载相互影响并使其复杂化:名称解析(因为作用域)和隐式类型转换。 如果在一个作用域中声明了一个函数,然后在内部作用域中声明了另一个同名函数,则有两种正常的可能的重载行为:内部声明掩盖了外部声明(无论签名如何),或者内部声明和外部声明都包含在重载中,只有在签名匹配时,内部声明才会屏蔽外部声明。第一个取自 C++:“在 C++ 中,没有跨作用域的重载。”[5] 因此,要获得不同作用域中声明的函数的重载集,需要将外部作用域中的函数显式导入到内部作用域,使用 隐式类型转换使函数重载复杂化,因为如果参数类型与重载函数之一的签名不完全匹配,但可以在类型转换后匹配,则解析取决于选择哪种类型转换。 这些能够以令人困惑的方式组合:例如,在内部作用域中声明的不精确匹配可以掩盖在外部作用域中声明的精确匹配。[5] 例如,有一个派生类,其重载函数带有一个 class B {
public:
void F(int i);
};
class D : public B {
public:
using B::F;
void F(double d);
};
如果不包含 附加说明如果一个方法设计有过多的重载,开发者可能很难通过阅读代码来辨别正在调用哪个重载。如果某些重载参数的类型是其他可能参数的继承类型(例如“对象”),则尤其如此。IDE 可以执行重载解析并显示(或导航到)正确的重载。 基于类型的重载也会妨碍代码维护,其中代码更新可能会意外更改编译器选择的方法重载。[6] 另见参考
外部链接 |
Portal di Ensiklopedia Dunia