看过很多遍重载重载重载重载重载重载,但是就是不会(不能用自己的语言去完美的描述)。这是一个很糟糕的地现象。
总结至关重要:
概念要清晰:
重载定义:
严格意义上来讲,重载应该叫 重载函数,因为只有函数才可以重载,
你不可能把
int a;
int b;
你不能把a,和b这两个变量看做是重载吧,所以记住以后没有重载这个词,全称叫重载函数。
重载函数定义:
如果在同一作用域内如果几个函数的名字相同,但是参数列表不同,我们叫这几个函数为重载函数。
重载函数是相对的概念,什么意思,就是单个函数,如果没有可以比较对象,那么他连重载函数的边都搭不上。
重载函数的形式:
重载形式相当重要,这是你理解重载函数定义的例子。
// 形式一:
{ // 同一作用域
int printf(int a);
int printf(char c);
int printf(int a,int b);
void printf(int a);
}
1,2重载函数;1,4非重载函数(记住重载函数概念中的参数列表);1,3重载函数。 2,3是,2,4是,3,4是。
重载函数底层实现:
编译器是如何区分这些重载函数的???
编译器很聪明将他们在编译(是预处理阶段还是编译阶段??)的时候,做了手脚。
一个问题:
是预处理阶段还是编译阶段??
凭知识点判断,预处理都干嘛,处理的要么是宏定义,要么是#include,所以一定不是预处理阶段。
编译过程包括哪几个主要阶段及每个阶段的主要功能。
词法分析阶段:读入源程序,对构成源程序的字符流进行扫描和分解,识别出单词,
语法分析阶段:机器通过词法分析,将单词序列分解成不同的语法短语,确定整个输入串能够构成语法上正确的程序。
语义分析阶段:检查源程序上有没有语义错误,在代码生成阶段收集类型信息
中间代码生成阶段:在进行了上述的语法分析和语义分析阶段的工作之后,有的编译程序将源程序变成一种内部表示形式
代码优化:这一阶段的任务是对前一阶段产生的中间代码进行变换或进行改造,目的是使生成的目标代码更为高效,即省时间和省空间
目标代码生成:这一阶段的任务是把中间代码变换成特定机器上的绝对指令代码或可重定位的指令代码或汇编指令代码
实际代码验证:
知识点: C++利用命名倾轧(name mangling)技术,来改名函数名,区分参数不同的同名函数。命名倾轧是在编译阶段完成的。
可以用VS或者在LInux系统用命令行验证 gcc xxx源文件 -E -o xxx输出文件.i (预处理阶段) ---》 g++ xxx.i -S -o xxx.s(生成汇编代码阶段)---》 g++ xxx.s -c -o main.o(真正的编译)
在Linux下:
用nm命令查看目标文件的符号清单
很明显在编译阶段编译器做了手脚,实现了重载函数。
在VS下查看底层代码:
obj文件目录下,
打开CMD命令行模式,用工具dumpbin执行以下命令对test.obj进行解析。
dumpbin /all test.obj > test.txt
obj解析信息会保存在test.txt文件中。
索引函数名:会发现有不一样的地方,说明同样是编译器动了手脚。
重载函数形式2:含有const的引用个指针
// 不属于重载,编译器报错
void recode(int a);
void recode(const int a);
// 属于重载
void recode(int& a);
void recode(const int& a);// 这个函数虽然语法上没报错,但是却没有实现重载功能。
// 属于重载
void recode(int* a);
void recode(const int* a);
{
int a = 10;
const int b = 20;
recode(a);
recode(b);
// 他们调用的都是void recode(const int& a)这个函数,所以实质上并没有发生重载,但是编译器不报错。
//
recode(&a);
recode(&b);
}
重载发生
总结:
重载条件:同一作用域;参数列表;带有const的引用或带有const的指针参数。