结论:
1:#include就是复制粘贴
2:C++编译的时候,在链接之前,各个文件之间实际上没有联系,只有到了链接的阶段,系统才会到各个cpp文件中去找需要的文件;
一:include的作用和头文件
就是复制张贴,所以,一定不能直接include源文件,也就是cpp文件,因为cpp文件中是函数的定义,一旦include了cpp文件,相当于在当前cpp文件又定义了一个相同名字的cpp文件,所以回报错,展示如下:
首先,项目的结构如下:这里,我们用不到src和include,以下均以main.cpp和main2.cpp来作为讲解;
其中main2.cpp内容如下:
这里展示直接include了cpp文件的结果如下:
编译报错如下:
此时如果想用main2.cpp中的内容,可以采用如下的方式,直接在main.cpp中声明main2,而后直接调用,展示如下:
结果如下:
结论如下:
这里我们在main.cpp中直接声明int main2(),其实和在头文件中声明函数是一样的,因为我们引用include头文件的时候就是赋值粘贴,所以相当于,我们这里的声明就是include了头文件;
由此引出我们的重点:声明,其实就是一个承诺,告诉系统,我肯定实现了这么一个函数也好,类也好,变量也好,反正我肯定实现了,我在当前cpp文件中就是要用它,你先别管我在哪实现了;而在编译的时候,各个cpp文件之间实际上是单独编译的,也就是说互不打扰,但是,编译的时候,各个类别,函数,变量啥的会生成一个符号表,链接的时候,各个cpp文件就拿着自己符号表里的东西去所有的编译结果里面去找,找到了变量,类别,函数实现的地方就把他们链接在一起,这也是为什么定义只能有一个的原因,否则链接的时候不知道链接哪一个;
所以结合上述内容我们可以理解头文件的作用了,其就是写了所要用到的函数的声明,然后include,也就是复制张贴到目标cpp文件中:其作用效果和我们上面这里直接再cpp文件里面声明一个函数是一样的;
很好,现在问题来了,那这样直接声明的函数为什么我们不用加extern呢?因为函数一般都是默认extern的,这部分参考:C++程序员应了解的那些事(82)~extern使用小结_c++ extern建议使用吗_so~what的博客-CSDN博客
引用外部变量的时候,我们是一定要extern的,但是引用外部函数的时候,不需要extern,实验展示如下:
如果a前面不加int的话则如下:
可以看到,变量a的外部引用是一定要加extern的;
实际上,这源自于我们所熟知的,定义只能有一次,而声明可以有无数次,而对于变量来说:
int a和extern int a=0和int a=0;这三者都是定义,只有extern int a是一个声明:
而对于函数来说,本来,也是和变量一样,比如,你在定义一个函数的时候,可以加上extern,就是说extern int func(){函数体}相当于上面的extern int a = 0;所以这就是一个定义,而当作为声明的时候就是说extern int func(int x, int y)相当于extern int a;但注意,当声明不加extern的时候,也就是int func(int x, int y)对应int a,注意,我们这里说的是对应,不是相当于,也就是说两者不一样,因为int a是一个定义,但是int func(int x, int y)是一个声明,因为它没有函数体;
这就是为什么函数的外部声明不需要加extern的原因,因为函数的声明和定义是完全不同的,迪尼亚需要有函数体,所以不加extern也可以区分,但是变量的声明和定义不加extern是无法区分的!!
参考自:C++程序员应了解的那些事(82)~extern使用小结_c++ extern建议使用吗_so~what的博客-CSDN博客
参考自:C++头文件源文件详解 - 知乎 (zhihu.com)
二:main函数入口
这个问题主要是,我们调试代码的时候,怎么去找函数入口,因为有一些函数入口并不是以main.cpp命名的,所以无法直接看到我们的函数入口在哪里,我现在采用的方式是利用vscode的查找功能,直接查int main字样;
至于系统怎么确认main函数入口的,就是上面说的main函数会生成特定的符号;