重载:指的是出现在相同作用域中的两个或两个以上具有相同函数名和不同形参列表的一组函数。
从其定义中我们看以总结出重载需要满足的条件:
1. 必须在相同的作用域中;
2. 函数名必须相同;
3. 形参列表必须不同(形参个数不同、形参类型不同、形参个数和类型都不同);
4. 返回值可以不同;
5. 具有相同或相似的功能(推荐)。
对于相同的函数名,编译器是如何进行匹配的呢?
其实编译器在对程序进行的编译的而过程中,会对每个函数定义一个内部名字来唯一地标识函数,所以对于Test()来说,可能生成的内部名字是_Test,而对于Test(int a)来说可能生成的就是Test_int,这样就可以精确地匹配到相应的函数,但是具体的内部名字的写法因编译环境而异。
从上面程序的输出结果来看,const造成了函数重载,这里需要注意的是:const只有在修饰指针变量或引用类型时才会造成重载,而对于普通数据类型不会造成重载。还有一点,就是这个程序中的GetName()的输出结果,有些人认为这也是一种函数重载,但是我认为这不应该归属为重载行为:
首先,从重载的定义来看,是否重载主要还是看形参列表是否相同,而没有明确说对于函数的修饰符的差异会造成函数重载;
其次,const在这里修饰GetName(),只是为了说明在该函数中,不能修改Person类的成员变量;
最后,从结果来看,似乎是满足重载,但是我认为这只是const的调用机制导致的。即:const修饰的对象只能调用const修饰的成员函数,而非const对象会优先调用非const成员函数,如果不存在非const成员函数,再调用const成员函数。
总结:const修饰形参中的指针变量或引用类型时才会引起函数重载,而修饰函数时,不会引起函数重载。
从其定义中我们看以总结出重载需要满足的条件:
1. 必须在相同的作用域中;
2. 函数名必须相同;
3. 形参列表必须不同(形参个数不同、形参类型不同、形参个数和类型都不同);
4. 返回值可以不同;
5. 具有相同或相似的功能(推荐)。
对于前四条,我们可以直接从概念中获取到,而对于第五条,我们只是推荐这样使用,具有相同的函数名,我们肯定是想实现相同的功能。
下面我们举个简单地例子:
#include <iostream>
using std::cout;
using std::endl;
void Test()
{
cout << "这是没有参数的Test函数" << endl;
}
void Test(int a)
{
cout << "这是有一个参数的Test函数" << endl;
}
int main(void)
{
Test(); // 输出结果:这是没有参数的Test函数
Test(1); // 输出结果:这是有一个参数的Test函数
return 0;
}
对于相同的函数名,编译器是如何进行匹配的呢?
其实编译器在对程序进行的编译的而过程中,会对每个函数定义一个内部名字来唯一地标识函数,所以对于Test()来说,可能生成的内部名字是_Test,而对于Test(int a)来说可能生成的就是Test_int,这样就可以精确地匹配到相应的函数,但是具体的内部名字的写法因编译环境而异。
对于上面的这种简单地函数重载我就不再赘述了。。。
在这里需要补充的是const关键字也可以引起函数重载,如下面的程序所示:
#include <iostream>
#include <cstring>
using std::cin;
using std::cout;
using std::endl;
class Person
{
public:
Person();
void SetName(char *name);
void SetName(const char *name);
char* GetName();
char* GetName() const;
private:
char *name;
};
Person::Person()
{
name = new char[20];
memset(name, 0, 20);
}
void Person::SetName(char *name)
{
strcpy(this -> name, name);
cout << "这是参数中没有const的SetName" << endl;
}
void Person::SetName(const char *name)
{
strcpy(this -> name, name);
cout << "这是参数中有const的SetName" << endl;
}
char * Person::GetName()
{
cout << "这是没有使用const修饰的GetName" << endl;
return (this -> name);
}
char * Person::GetName()const
{
cout << "这是使用const修饰的GetName" << endl;
return (this -> name);
}
int main(void)
{
Person p;
char *name = "Freeman";
p.SetName(name); // 输出结果:这是参数中没有const的SetName
p.SetName("Freeman"); // 输出结果:这是参数中有const的SetName
p.GetName(); // 输出结果:这是没有使用const修饰的GetName
const Person p2;
p2.GetName(); // 这是使用const修饰的GetName
return 0;
}
从上面程序的输出结果来看,const造成了函数重载,这里需要注意的是:const只有在修饰指针变量或引用类型时才会造成重载,而对于普通数据类型不会造成重载。还有一点,就是这个程序中的GetName()的输出结果,有些人认为这也是一种函数重载,但是我认为这不应该归属为重载行为:
首先,从重载的定义来看,是否重载主要还是看形参列表是否相同,而没有明确说对于函数的修饰符的差异会造成函数重载;
其次,const在这里修饰GetName(),只是为了说明在该函数中,不能修改Person类的成员变量;
最后,从结果来看,似乎是满足重载,但是我认为这只是const的调用机制导致的。即:const修饰的对象只能调用const修饰的成员函数,而非const对象会优先调用非const成员函数,如果不存在非const成员函数,再调用const成员函数。
总结:const修饰形参中的指针变量或引用类型时才会引起函数重载,而修饰函数时,不会引起函数重载。