函数重载
规则
-
函数名相同
-
参数个数不同、参数类型不同、参数顺序不同
//重载例子 void test() {}; void test(int a) {}; void test(int a,int b) {}; void test(double a,int b) {}; void test(int a,double b) {};
注意
-
返回值类型与函数重载无关
-
调用函数时,实参的隐式类型转换可能会产生二义性
int test() {}; void test() {}; //不能实现重载,产生二义性
本质
- 采用了name mangling或者叫name decoration技术
- C++编译器默认会对符号名(比如函数名)进行改编、修饰, 有些地方翻译为“命名倾轧”
- 重载时会生成多个不同的函数名,不同编译器(MSVC、g++)有不同的生成规则
重载实现本质
<1> name mangling C++编译器默认会对符号名(比如函数名)进行改编、修饰
例:下图为C++程序
#include<iostream>
#include<string>
using namespace std;
void display()
{
cout << "void" << endl;
};
void display(long a)
{
cout << "long" << endl;
};
void display(int a, int b)
{
cout <<"int int"<< endl;
};
void display(double a, int b)
{
cout << "double int" << endl;
};
void test(int a, double b)
{
cout << "int double " << endl;
};
int main(void)
{
display();
display(100l);
display(1,2);
display(10.0, 5);
display(5,10.0);
system("pause");
}
输出:
voidtxt
long
int int
double int
int int
下图一是在VS2015
环境下的反编译代码,通过IDA软件,可以看到红框处对应四个display函数,函数名由"sub_" + 一个地址构成,说明编译器确实对函数名进行改编、修饰,而这就是机器分辨重载函数的方式。
第二张图是在VS2017
的环境下,编译器修饰重载函数的方法,“函数名” + “__” + “数字”,
所以不论是什么编译器,函数重载的本质就是编译器对相同命名函数进行修饰、改编处理。
提示:
VS中Debug模式与release模式
- Debug模式:很多调试信息,生成的可执行文件比较臃肿
- Release模式:去除调试信息,生成的可执行文件比较精简、高效
使用IDA看到上图效果需要在项目属性中将优化禁用,并在release,模式下生成exe