Aoki Job Seeker

函数重载

2019-03-21
C++

函数重载



写在前面

如果同一个作用域内的几个函数名字相同,但是形参列表不同,我们称之为重载函数。
实现函数重载的条件:

  • 同一个作用域
  • 参数个数不同
  • 参数类型不同
  • 参数顺序不同

函数的名字仅仅是让编译器知道它调用的是哪个函数,而函数重载在一定程度上可以减轻程序员起名字、记名字的负担。

1.定义重载函数

下面是一个函数重载的例子。函数重载使得我们可以定义一组函数,名字都为func。

#include <iostream>
#include<string>
using namespace std;

namespace A
{
	void func()
	{
		cout << "没有参数" << endl;
	}
	void func(int a)
	{
		cout << "a=" << a << endl;

	}
	void func(string a)
	{
		cout << "a=" << a << endl;
	}

	void func(int a, float b)
	{
		cout << "a=" << a << "  b=" << b << endl;
	}
	void func(string a, int b)
	{
		cout << "a=" << a << "  b=" << b << endl;
	}

}

void test()
{
	A::func();
	A::func(15);
	A::func("Aoki");
	A::func(12, 3.12);
	A::func("Aoki", 15);
}



int main()
{
	test();
}


输出结果如下:

虽然我们定义的是五个函数各不相同,但是它们都有同一个名字。编译器根据实参的类型来决定应该调用哪一个函数。
对于重载的函数来说,它们应该在形参数量或形参类型上有所不同。
对于函数的重载,我们不能以函数的返回值作为重载的条件,这是为什么呢?
当编译器能从上下文中确定唯一的函数时,如int ret=func(),这样就不会有问题。但是我们在编写程序的过程中还可以忽略它的返回值,那么这个时候,一个函数为 void fun(int x),另一个为 int func(int x),当我们直接调用func(10),这时候编译器就不确定该调用哪个函数。所以,在C++中禁止使用返回值作为重载的条件。

对于函数重载,我们还应当注意避免二义性。举例如下:

#include <iostream>
#include<string>
using namespace std;

namespace A
{
	void func(string a)
	{
		cout << "a=" << a <<  endl;
	}
	void func(string a, int b=10)
	{
		cout << "a=" << a << "  b=" << b << endl;
	}

}

void test()
{
	
	//A::func("Aoki");//出现二义性
}



int main()
{
	test();
}

错误提示如下:

在使用函数重载的同时,我们应该注意避免这种情况出现。

2.调用重载的函数

定义了一组重载函数之后,我们需要以合理的实参来调用它们。函数匹配是指一个过程,在这个过程中我们把函数调用与一组重载函数中的某一个关联起来,函数匹配也叫重载确定。编译器首先将调用的实参与重载集合中对的每一个函数的形参进行比较,然后根据比较的结果决定到底调用哪个函数。
在很多情况下,我们很容易判断某次调用是不是合法对的,以及当调用合法时该调用哪个函数。通常,重载集中的函数区别明显,它们要不然是参数的数量不同,要不然就是参数类型毫无关系。此时,确定调用哪个函数比较容易。但是在另外一些情况下要想选择函数就比较困难了。比如当两个重载函数参数数量相同,且参数类型可以相互转换。
当调用重载函数时有三种可能的结果:

  • 编译器找到一个与实参最佳匹配的函数,并生成了调用该函数的代码。
  • 找不到任何一个函数与调用的实参匹配,此时编译器发出无匹配的错误信息。
  • 有多于一个函数可以匹配,但是每一个都不是明显的最佳选择。此时也发生错误,称为二义性调用。

3.函数重载实现原理

编译器为了实现函数重载,为我们做了一些幕后的工作,编译器用不同的参数类型来修饰不同的函数名,比如 void func();编译器可能会将函数名修饰成—func,当编译器碰到void func(int x),编译器可能会将函数名修饰为_func_int,当编译器碰到void func(int x,char c),编译器可能会将函数名修饰为_func_int_char,这里使用可能,是因为编译器如何修饰重载的函数名称并没有一个统一的标准,所以不同的编译器可能会产生不同的内部名。







The End



Similar Posts

下一篇 拷贝构造函数

Comments