1.函数重载
什么是函数重载?
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型
不同的问题。
区分:
1.参数个数不同;
2.参数类型不同;
3.参数类型顺序不同。
注意:不要把返回值当作区分的条件,返回值不同,无法区分,所以返回值不是重载的条件。
小细节:像 无参类型函数 和 全缺省型函数 它们构成函数重载,但是调用的时候会发生歧异;这种例子还有,具体根据实际分析。
2.C++支持函数重载的原理------名字修饰
这里只是简单的写一下:
为什么C++支持函数重载,而C语言不支持函数重载?
基础知识支撑:
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
例子:
将上面的程序运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
这个过程,前几步都是各自对应单线执行,直到链接这一步,它是将所有的文件合并到一起成成一个文件,这一步很重要。
分析:
函数有一堆要执行的指令:函数地址,第一句指令的地址;
Test.cpp --> Test.o 只有函数声明,可以通过,因为语法检查是匹配的,但是没有函数地址;
有函数的定义,才能生成函数一堆汇编指令,就是第一句指令的地址,才是函数的地址,Stack.cpp --> Stack.o 才有函数的地址;
到了链接,将 Test.o 和 Stack.o 链接到一起,合并到一起,然后就要用 StackInit 这个函数名去Stack.o里面找它的地址(具体去哪找呢? 每个 .o文件里面都有对应的符号表)。
解释:
回到问题的开始,为什么 C++ 支持函数重载,而 C 不支持呢?
链接时: 1.直接用函数名去查找,是否支持重载,不支持。(C语言)
2.用修饰后的函数名(函数名修饰规则)去查找,就可以支持重载了。 (C++)
我们用 Linux下的 gcc 和 g++ 演示:
通过下面我们可以看出 gcc的函数修饰后名字不变,
而 g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】。
gcc:
g++:
注意:不同的编译器有不同的函数名修饰规则(一般来说,【公共的前缀 + 函数长度 + 函数名 + 类型首字母】)。
3.引用:
引用的概念:
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。
使用格式:类型& 引用变量名(对象名) = 引用实体;
引用的特性:
1. 引用在定义时必须初始化
2. 一个变量可以有多个引用
3. 引用一旦引用一个实体,再不能引用其他实体
注意:引用类型必须和引用实体是同种类型的。
常引用:
总结一下:值之间没有权限的缩小和放大,就是拷贝(就是把它想成以前的赋值);
引用和指针有权限缩小和放大的概念;
隐式类型转换以及强制类型转换会存在临时变量,临时变量是常变量(只读不可
写)有权限放大的可能;
权限可以缩小,不能放大。
使用场景:
1.做参数
2.做返回值
传值、传引用效率比较:
以值作为参数或者返回值类型,在传值或返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大的时候,效率就更低。
引用和指针的区别:
在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间;
在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。
总结为以下几点:
1. 引用概念上定义一个变量的别名,指针存储一个变量地址;
2. 引用在定义时必须初始化,指针没有要求;
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体;
4. 没有NULL引用,但有NULL指针(不是绝对的);
5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节);
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小;
7. 有多级指针,但是没有多级引用;
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理;
9. 引用比指针使用起来相对更安全。