函数重载
自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”
函数重载概念
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
注意:同一作用域下,函数重载的构成只与同名函数的形参列表有关 !!!
-
形参的参数个数不同
void Fun(int a)
{cout << "Fun(int a)" << endl;
}
void Fun(char c, int a)
{cout << "Fun(int a, char c)" << endl;
}
int main()
{ //编译器会根据形参自动识别调用那个函数Fun(10); //Fun(int a)Fun('C',10); //Fun(int a, char c)return 0;
}
- 形参的类型不同
void Fun(int a)
{cout << "Fun(int a)" << endl;
}
void Fun(char c)
{cout << "Fun(char c)" << endl;
}
int main()
{Fun(10); //Fun(int a)Fun('C'); //Fun(char c)return 0;
}
- 形参的类型顺序不同
void Fun(int a, char c)
{cout << "Fun(int a, char c)" << endl;
}
void Fun(char c, int a)
{cout << "Fun(char c, int a)" << endl;
}
int main()
{Fun(10,'A'); //Fun(int a, char c)Fun('C',20); //Fun(char c, int a)return 0;
}
C++支持函数重载的原理
为什么C++支持函数重载?,而C语言却不支持重载呢?C++支持重载的原因又是什么呢?这里就要聊到C/C++程序的编译与链接了,至于这部分内容我在《C语言编译与链接》一文中有更加详细的讲解,文章链接:http://t.csdnimg.cn/oTZlJ。
在这里我简述一下:一个程序运行起来需要经历预处理、编译、汇编、链接四个阶段。在预处理阶段就是把 .c文件处理成 .i文件,把相应的头文件替换下来;编译阶段把 .i文件处理成 .s(汇编)文件,并进行语法分析、词法分析、语义分析还有符号汇总;汇编阶段把 .s文件处理成 .o或者 .obj文件,并把汇编指令转换为二进制指令,形成符号表;链接阶段把各个源文件合并,符号表重定位,生成 .exe文件。
其实,在函数重载方面C程序与C++程序在运行时的前三个阶段基本上是类似的,只有在链接阶段,C程序是直接通过函数的名字去查找的,如果出现同名的函数,编译器就不知道去调用哪一个函数,所以就会报错,因此不支持重载;而C++程序是直接用形参修饰过的函数名字去查找的,所以就算是同一函数名,只要形参不同(参数个数 或 类型 或 类型顺序),编译器就可以识别,因此支持重载。
为了方便我们更好的理解,请看下图:
ps. 下图中是相应代码对应的汇编代码,这里我们不需要看懂,只需理解红色方框里的内容即可;不同编译器的函数名修饰规则不同
从汇编代码中可以看出:C语言环境下函数修饰后名字不变
从汇编代码中可以看出:在C++的环境下函数修饰后变成【_Z+函数长度+函数名+类型首字母】
通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。另外,如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。
引用
引用概念
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
使用语法:类型& 引用变量名(对象名) = 引用实体;
说了这么多,请看代码:
void TestRef()
{int a = 10;int& ra = a;//<====定义引用类型printf("%p\n", &a);printf("%p\n", &ra);
}
注意:引用类型必须和引用实体是同种类型的
引用特性
- 引用在定义时必须初始化
- 一个变量可以有多个引用
- 引用一旦引用一个实体,再不能引用其他实体
void TestRef()
{int a = 10;// int& ra; // 该条语句编译时会出错,因为没有初始化int& ra = a;// 多次引用int& rra = a;printf("%p %p %p\n", &a, &ra, &rra);
}