目录
- 函数重载
- 函数名修饰规则
函数重载
C语言不允许同名函数
CPP可以,但是要求构成函数重载
函数名相同,参数不同(参数类型、参数个数、参数类型的顺序),返回值不同不能构成重载
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
void Swap(int* p1, int* p2)
{
//...
}
void Swap(double* p1, double* p2)
{
//...
}
int main()
{
cout << Add(1, 2) << endl;
cout << Add(1.1, 2.2) << endl;
int i = 1, j = 2;
double k = 1.1, l = 2.2;
Swap(&i, &j);
Swap(&k, &l);
//cout << i;
//cout << k;
return 0;
}
cout<<i;
cout<<k;
自动识别类型的原理就是函数重载,这是两个函数调用然后是int就匹配int是double就匹配double
不同域就不存在函数重载的问题了
namespace dz1
{
void func(int x)
{}
}
namespace dz2
{
void func(double x)
{}
}
因为相同命名空间会自动合并,所以如果两个命名空间都是dz1时,可以构成函数重载
函数重载跟缺省参数没有关系
函数名相同参数不同就构成重载
// 构成函数重载
void func(int a)
{
cout << "void func(int a)" << endl;
}
void func(int a, int b = 1)
{
cout << "void func(int a, int b)" << endl;
}
int main()
{
func(1, 2);
// 调用存在歧义,不知道调用哪个
// func(1);
return 0;
}
是重载没错,但是调用的时候就出问题了
func(1, 2);没有歧义
func(1);调用存在歧义
函数名修饰规则
为什么C++支持函数重载,而C语言不支持函数重载呢?
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
- 实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们可以知道,【当前Test.cpp中调用了b.cpp中定义的func函数时】,编译后链接前,Test.o的目标文件中没有func的函数地址,因为func是在b.cpp中定义的,所以func的地址在b.o中。
- 链接阶段就是专门处理这种问题,链接器看到Test.o调用func,但是没有func的地址,就会到b.o的符号表中找func的地址,然后链接到一起
- 链接时,面对func函数,链接接器会使用名字去寻找地址
c语言找的时候是用函数名去找的:
c语言用名字找地址的机制是直接用函数名充当在符号表中的名字,在符号表中找函数地址的时候相同名字就分不清了,所以c语言不允许重名
c++把两个函数区分开来的方法和函数名修饰规则有关,不同的编译器有不同的规则,vs的规则比较复杂,Linux下g++的修饰规则比较简单易懂
Windows下vs
只给声明不给定义的时候vs会出现报链接错误,(有声明没有定义无法生成地址,在符号表中拿名字找不到地址,就会报这个错误) 不是c语言那样拿func这个名字去找,而是下图括号中修饰以后的函数名去找。两个修饰后的名字很长,但是有一些细节可以观测,比如H代表int,N代表double,本质是把类型带进名字中了
linux下g++
linux下的名字是_Z是前缀,4是函数名的字节数,然后后面的 i d,i是int,d是double
c++找函数地址,函数的地址本质上是第一句指令的地址
把类型带进名字中
所以类型的个数不同,类型不同,类型的顺序不同,修饰出来的名字都不同,就可以区分出来,找到对应地址。
在函数修饰规则中没有代入返回值。返回值不同不能构成函数重载也可以解释。
如果函数修饰规则中代入返回值,返回值不同能不能构成函数重载?
不能。
函数修饰规则能解决符号表的问题,但是调用还是不知道调用谁( 除非把调用规则也更改了,调用的时候void func (1.1 , 1)这样调用,这样很难设计 )