函数重载与函数模板
函数重载
函数组成
返回类型 函数名称(参数列表){函数体}
函数签名:函数名称(参数列表)
C++ 允许定义同名函数,前提是它们具有不同的签名。这被称为函数重载 。
C++ 编译器通过检查调用中参数的数量、类型和顺序来选择要调用的适当函数。
//重载函数
//函数名称一致,但参数列表中参数类型、顺序不同
int square(int x){return x*x;
}
double square(double y){return y*y;
}
函数重载的目的:函数重载用于创建多个同名函数,这些函数执行类似任务,但处理不同类型的数据。
编译器如何区分重载函数
重载函数通过其签名来区分。签名是函数名称及其参数类型(按顺序排列 )的组合。类型安全链接可确保调用恰当的函数,且实参的类型与形参的类型相符。为实现类型安全链接,编译器会在内部对每个函数标识符进行编码,编码时纳入其参数的类型 —— 这一过程称为名称修饰(name mangling )。这些编码因编译器而异,因此,要为特定平台创建可执行文件而进行链接的所有内容,都必须使用该平台对应的同一编译器进行编译。
下图为由 GNU C++ 在汇编语言中生成的经过修饰的函数名称 。
如果函数签名一致,但返回类型不同,会造成编译错误
创建具有相同参数列表但不同返回类型的重载函数会导致编译错误。编译器仅通过参数列表来区分重载函数,这些函数的参数数量不必相同。
如果一个函数省略了默认参数,可能会与另一个重载函数的调用形式完全相同,这也会引发编译错误。
例如,若存在一个显式不接受任何参数的函数,以及另一个同名但包含所有默认参数的函数,那么当尝试以不传递任何参数的方式调用该函数名时,就会导致编译错误——编译器无法明确确定应选择哪个版本的函数。
函数模板
函数模板产生的背景
重载函数通常对不同数据类型执行类似的操作。如果对于每种数据类型,程序逻辑和操作都是相同的,那么使用函数模板可以更紧凑、便捷地实现重载。你只需编写一个函数模板定义,C++ 会自动生成独立的函数模板特化版本(也称为模板实例化),以适配所提供参数类型的每种调用类型。因此,单个函数模板定义了一个重载函数家族。使用模板进行编程也称为泛型编程。
定义了一个最大值函数模板,该模板返回三个值中的最大值
所有函数模板定义均以template关键字开头,后跟包含在尖括号(<>)中的模板参数列表。
模板参数列表中的每个参数都以关键字typename或keyword class作为前缀。
类型参数是基本类型或用户定义类型的占位符。这些占位符(在本例中为T)用于指定函数参数的类型、函数的返回类型,以及在函数定义体中声明变量。函数模板的定义方式与其他函数类似,但使用类型参数作为实际数据类型的占位符。
头文件maximum.h
// template <关键字 占位符>
template <typename T> // or template <class T>
T maximum(T value1, T value2, T value3) { T maximumValue{value1}; // assume value1 is maximum // determine whether value2 is greater than maximumValueif (value2 > maximumValue) { maximumValue = value2; } // determine whether value3 is greater than maximumValueif (value3 > maximumValue) { maximumValue = value3; } return maximumValue; }
main.cpp
// Function template maximum test program.
#include <iostream>
#include "maximum.h" // include definition of function template maximum
using namespace std;int main() {// demonstrate maximum with int valuescout << "Input three integer values: ";int int1, int2, int3;cin >> int1 >> int2 >> int3;// invoke int version of maximumcout << "The maximum integer value is: "<< maximum(int1, int2, int3); // demonstrate maximum with double valuescout << "\n\nInput three double values: ";double double1, double2, double3;cin >> double1 >> double2 >> double3;// invoke double version of maximumcout << "The maximum double value is: "<< maximum(double1, double2, double3);// demonstrate maximum with char valuescout << "\n\nInput three characters: ";char char1, char2, char3;cin >> char1 >> char2 >> char3;// invoke char version of maximumcout << "The maximum character value is: "<< maximum(char1, char2, char3) << '\n';}