函数重载也叫函数多态,多态指的是有多种形式。
函数重载(function overloading)是在一个类或命名空间中,可以有多个同名函数,但是它们的参数列表(也叫函数特征标)不同。
如果两个函数的参数数目和类型相同,同时参数的排列顺序也相同,则它们的特征标相同,而变量名是无关紧要的。如果参数数目,参数顺序,参数类型不同的话,则特征标不同。
通过函数重载,可以根据不同的参数类型和个数,为同一个函数名定义多个具有相似功能但参数不同的函数。
函数重载的主要目的是提供一种方便的方式来定义和调用具有相似功能的函数,使代码更加灵活和可读性更高。
函数重载时,编译器会根据传递给函数的参数的类型和个数,自动选择合适的函数进行调用。编译器根据参数列表中的类型、个数和顺序来确定调用哪个函数。在调用函数时,不需要显示地指定具体的函数名,只需要提供正确的参数即可。
下面是一个简单的函数重载的示例:
#include
using namespace std;
int add(int a, int b) {
return a + b;
}
float add(float a, float b) {
return a + b;
}
int main() {
cout << add(1, 2) << endl; // 调用int add(int a, int b)
cout << add(1.5f, 2.5f) << endl; // 调用float add(float a, float b)
return 0;
}
在上述示例中,我们定义了两个名为add的函数,一个接受两个int类型的参数,另一个接受两个float类型的参数。当我们调用add函数时,编译器会根据提供的参数类型自动选择相应的函数进行调用。
通过函数重载,我们可以用相同的函数名来实现不同类型的参数和不同的功能,提高代码的可读性和灵活性。
#include
using namespace std;
//1号
double A(int a,int b,double c)
{
return a * b * c;
}
//2号
double A(int a, double b, int c)
{
return a * b * c;
}
//3号
double A(double a, int b)
{
return a * b;
}
//4号
int A(int a, int b)
{
return a * b;
}
int main()
{
int a = 3; int b = 8; double c = 3.0;
cout << A(a, b, c) << endl;//匹配1号,结果是72
cout << A(a, c, b) << endl;//匹配2号,结果是72
cout << A(c, a) << endl;//匹配3号,结果是9
cout << A(a, b) << endl;//匹配4号,结果是24
}
这里我们验证了不同特征标的情况下,函数匹配机制 ,结果如上,我就不多说了,自己体会
至于为什么用cout打印double类型是个整数,自己去看看cout的特性吧!!
int A(int a)
{
return a * 2;
}
double A(int a)
{
return a / 3.0;
}
//这是不可以的
但是我们得知道不是返回类型必须得设置成相同的,返回类型可以不同,但是特征标必须不同
上面这个例子不行是因为它们的特征标相同
#include
using namespace std;
int A(int a)
{
return a * 2;
}
int A(int b)
{
return b *3;
}
int main()
{
int a = 3;
cout << A(a) << endl;
}
//这是不行的
#include
using namespace std;
int A(int a, int b = 10)
{
return a * b;
}
int A(int a)
{
return a * 100;
}
int main()
{
int a = 1;
cout << A(a) << endl;//会发生错误
}
这是不被允许的,编译器不知道调用哪个函数,会出大问题
如果传入的参数没有匹配的原型,编译器不会自动停止使用其中的某个函数,因为c++将尝试用标准类型转换强制进行匹配
话不多说,上例子
#include
using namespace std;
int A(int a, int b)
{
return a * b;
}
int main()
{
int a = 1; double b = 3.0;
cout << A(a,b) << endl;//结果是3,将double强制转换为int
}
但是要是要是下面这种情况,编译器就会报错啦
#include
using namespace std;
int A(int a, int b)
{
return a * b;
}
int A(int a, char b)
{
return a * b;
}
int main()
{
int a = 1; double b = 3.0;
cout << A(a,b) << endl;//编译器会报错
}
原因是有2个将int作为第一个参数的原型,因此有两种转换b的方式。在这种情况下,c++将拒绝这种函数调用,并将其视为错误
我们都知道普通函数的const形参可以接收const实参和非const实参,但是如果遇到下面这种情况,编译器该怎么办呢?
int A(const int a)
{
return a * 1;
}
int A(int a)
{
return a * 2;
}
//系统会报错
答案是会报错哦!!! c++不允许这么做,因为c++会将除了引用和指针外的任何变量作函数形参时的 const和非const形式视作一种类型
方便对比,我们再引入普通函数看看
int A(const int a)
{
return a * 1;
}
int B(int a)
{
return a * 2;
}
//不会有问题
这就完全没有问题的
我们再试试上面那种操作
#include
using namespace std;
int A(const int& a)
{
return a * 1;
}
int A(int&a)
{
return a * 1;
}
int B(const int* a)
{
return a[0];
}
int B(int* a)
{
return a[1];
}
int main()
{
int a = 1;
const int b = 2;
cout << A(a) << endl;//结果是1
cout << A(b) << endl;//结果是2
const int c[10] = { 1,2,3,4,5,6,7,8,9,10 };
int d[10] = { 1,2,3,4,4,5 };
cout << B(c) << endl;//结果是1
cout << B(d) << endl;//结果是2
}
结果表明,c++在面对引用和指针作函数形参的时候会将const和非const视作两种类型
有人想重载int和int&两种版本的函数,但是c++是不允许这么做的
话不多说,上例子
#include
using namespace std;
int A(int& a)
{
return a*1;
}
int A(int a)
{
return a*2;
}
int main()
{
int a = 9;
cout << A(a) << endl;//系统会出错
}
上面这样子无法运行的原因是编译器将类型引用和类型本身视作同一个特征标 ,所以禁止这样子做