一、函数重载的概念
- 函数重载是 C++ 中的一个特性,它允许在同一个作用域中有多个同名函数,但是这些函数的参数列表(参数的个数、类型或者顺序)不同。函数重载的目的是为了让程序员可以用一个函数名来执行相似的操作,只是操作的数据类型或者参数个数等可能不同。
- 例如,我们可以有一个函数用来计算两个整数的和,还有一个同名函数用来计算两个浮点数的和。这样,根据传入参数的类型,编译器能够自动选择正确的函数来执行。
1、函数重载的规则
- 参数个数不同:
- 示例代码如下:
int add(int a, int b) {return a + b;}int add(int a, int b, int c) {return a + b + c;}
- 在这个例子中,有两个
add
函数,一个接受两个整数参数,另一个接受三个整数参数。当调用add
函数时,编译器会根据传入的参数个数来确定调用哪一个函数。
2、参数的类型不同
int add(int a, int b) {return a + b;}float add(float a, float b) {return a + b;}
- 这里同样有两个
add
函数,一个用于处理两个整数相加,另一个用于处理两个浮点数相加。如果传入两个整数,编译器会调用第一个add
函数;如果传入两个浮点数,编译器会调用第二个add
函数。
3、参数的顺序不同
void print(int a, char b) {std::cout << a << " " << b << std::endl;}void print(char b, int a) {std::cout << b << " " << a << std::endl;}
- 这两个
print
函数,参数的类型相同,但是顺序不同。当调用print
函数时,编译器会根据传入参数的顺序来确定调用哪一个函数。
二、函数重载原理
- 在 C++ 中,编译器会对函数名进行名字修饰(name mangling)。名字修饰是一种在编译阶段将函数名和它的参数类型等信息编码成一个唯一的内部名称的过程。
- 例如,对于非重载函数
int func(int a)
,在编译后的目标文件中,函数名可能就是func
。但是对于重载函数,如int func(int a)
和float func(float a)
,编译器会根据参数类型等信息对函数名进行修饰,使得它们在目标文件中有不同的内部名称,这样链接器就可以正确地将调用和对应的函数实现链接起来。
三、函数重载和函数重写
- 函数重载:是在同一个类或者同一个作用域中,函数名相同但参数列表不同的多个函数。函数重载发生在编译时,编译器根据函数调用时传入的参数来确定调用哪一个重载函数。
- 函数重写(覆盖):主要是在继承关系中,子类重新定义了父类中的虚函数,函数签名(函数名、参数列表、返回值类型)必须相同(协变返回类型除外)。函数重写发生在运行时,通过虚函数表机制来实现动态绑定,根据对象的实际类型来决定调用父类的函数还是子类的函数。
注意
int add(int a, int b) {return a + b;}float add(int a, int b) {return (float)(a + b);}
- 编译器在编译时会根据参数列表来选择函数,如果找不到匹配的函数或者有二义性(比如有两个重载函数都可以匹配调用,但编译器无法确定哪一个更合适),就会产生编译错误。