函数重载决议(Function Overloading Resolution)是C++中确定调用哪个重载函数的过程。当存在多个同名函数但参数类型不同时,编译器需要根据函数调用的上下文来决定具体调用哪一个函数。以下是函数重载决议的一些关键点:

  1. 参数数量匹配: 编译器首先会检查调用时提供的参数数量是否与候选函数的参数列表匹配。如果参数数量不匹配,这些候选函数将被排除。

  2. 参数类型匹配: 对于参数数量匹配的候选函数,编译器会检查每个参数的类型是否与调用时提供的实参类型一致或可以隐式转换。最佳匹配是所有参数都不需要转换或只需要进行标准转换。

  3. 标准转换: C++定义了几种标准转换,包括:

    • 精确匹配(Exact match)
    • 整型提升(Integral promotion)
    • 浮点数提升(Floating-point promotion)
    • 无定义的转换(Unambiguous integer conversions)
    • 算术转换(Arithmetic conversions)
    • 指针转换(Pointer conversions)
    • 引用绑定(Lvalue-to-rvalue conversions for references)
  4. 用户定义的转换: 如果标准转换不适用,编译器会考虑用户定义的转换(如构造函数、转换运算符等)。

  5. 构造函数调用: 如果实参是一个对象,编译器会考虑使用该对象类型的构造函数来创建一个临时对象,然后使用这个临时对象进行函数调用。

  6. 函数的可访问性: 候选函数的可访问性(public、protected、private)也会影响重载决议。

  7. 最匹配的函数: 编译器会选择需要最少转换的候选函数。如果存在多个具有相同最少转换的候选函数,那么:

    • 如果函数是模板,优先选择模板函数。
    • 如果有多个模板或非模板函数,编译器可能会根据函数声明的顺序来选择(这通常是未定义行为)。
  8. 歧义解决: 如果存在多个候选函数,且它们需要相同数量的转换,这称为重载歧义(Overload Ambiguity)。编译器将报错,因为无法确定调用哪一个函数。

  9. SFINAE(Substitution Failure Is Not An Error): 在模板编程中,如果模板实例化失败,但失败的原因不是语法错误或类型错误,编译器将忽略这个候选函数而不是报错。

函数重载决议是一个复杂的过程,涉及到类型匹配、转换成本评估和模板匹配等多个方面。了解这些规则有助于编写更清晰、更可维护的代码。