重载分辨率由 C++ 标准的第 13.3 节定义(至少 C++03 和 C++11)。分为三个部分:
- 确定候选函数,
- 从候选函数中确定可行函数,
- 选择最佳可行函数。
候选函数
由于add 命名一个函数(而不是一个对象),第 13.3.1.1.1 节定义了如何确定候选函数。由于add 不合格(不包含. 或-> 运算符),适用第3 条(取自C++11 的draft n3337):
在不合格的函数调用中,名称不是由 -> 或 限定的。运算符,并且具有更一般的主表达式形式。按照函数调用中名称查找的常规规则 (3.4) 在函数调用的上下文中查找名称。通过该查找找到的函数声明构成候选函数集。由于名称查找的规则,候选函数集由 (1) 完全由非成员函数或 (2) 完全由某个类 T 的成员函数组成。在情况 (1) 中,参数列表与调用中的表达式列表。 [...]
简而言之,候选函数是在函数调用上下文中通过标准名称查找找到的函数。名称查找在第 3.4 节中定义。通常,第 3.4.2 节(与参数相关的名称查找)会找到额外的候选函数,但所讨论的函数调用中没有参数,因此只有第 3.4.1 节很重要。特别是第 6 条:
在函数的 declarator-id 之后的函数定义中使用的名称是命名空间 N 的成员(其中,仅出于说明的目的,N 可以表示全局范围)应在使用它的块或其封闭块之一(6.3)中使用之前声明,或者,在命名空间 N 中使用之前声明,或者,如果 N 是嵌套命名空间,则应在使用之前声明N 的封闭命名空间之一。
简而言之,搜索当前命名空间和任何父命名空间,并且只考虑已经声明的函数。在示例代码中,在全局命名空间中main 之前声明的名称为add 的任何函数都是候选函数:add(int, int) 和add()。如果您要在main 之后声明(例如)一个函数add(float, float),它就不是候选函数。
可行的功能
第 13.3.2 节:
2 首先,要成为一个可行的函数,候选函数应有足够的参数以在数量上与列表中的参数一致。
- 如果列表中有 m 个参数,则所有具有恰好 m 个参数的候选函数都是可行的。
- 参数少于 m 个的候选函数只有在其参数列表中有省略号时才可行 (8.3.5)。出于重载决议的目的,没有对应参数的任何参数都被视为“匹配省略号”(13.3.3.1.3)。
- 仅当 (m+1)-st 参数具有默认参数 (8.3.6) 时,具有多于 m 个参数的候选函数才是可行的。出于重载解析的目的,参数列表在右侧被截断,因此正好有 m 个参数。
3 其次,要使 F 成为可行的函数,每个参数都应存在一个 隐式转换序列 (13.3.3.1),该序列将该参数转换为 F 的相应参数。如果参数具有引用类型,隐式转换序列包括绑定引用的操作,以及对非 const 的左值引用不能绑定到右值以及右值引用不能绑定到左值这一事实会影响函数的可行性(参见13.3.3.1.4)。
参数列表有 0 个参数。 add() 有 0 个参数,所以它是可行的。 add(int, int) 有 2 个参数,但第一个有一个默认参数,所以它是可行的。由于调用中没有参数,因此第 3 条中的转换不会起作用,但重要的是要注意该子句,尤其是它指出声明为 int foo(int&) 的函数不能绑定到函数调用foo(0),因为non-const reference(例如int&)不能绑定到右值(例如文字0)。但是,int foo(const int&) 可以绑定到foo(0)。
最佳功能
§ 13.3.3 定义了一个函数在名称解析方面如何被认为比另一个函数“更好”:partial ordering 函数:
- 某些转换比其他转换“更好”(第 13.3.3.2 节),使用更好的参数转换的函数是更好的函数。
- 如果 1 不能确定更好的函数,则非模板函数优于模板函数。
- 如果 2 不能确定更好的函数,则比另一个更专业的函数模板专业化更好(“更专业化”是 § 14.5.6.2 中定义的偏序)。
由于没有参数,因此不能使用标准 1。 add() 和 add(int,int) 都不是模板,因此 2 和 3 都不能使用。简而言之,没有一个功能比另一个更好。
最后,§ 13.3.3 2 确定最终结果:
如果恰好有一个可行函数比所有其他可行函数更好,那么它就是重载决议选择的那个;否则调用格式不正确。
由于示例代码中有两个可行的函数,因此调用格式不正确。