标签:com median 声明和定义 编译链接 处理 bin ext 不同 注意
最近一直有同学问为何会出现这种编译错误,既然需求如此之大,我就写篇文章解释一下吧。
先解释一下,代码在编译的时候,你的电脑中发生了一件什么事吧。
编译指的就是把人类可以理解的文本程序“翻译”成电脑可以识别执行的指令清单,充当翻译官的角色的就是编译器。
一般来说,童鞋使用的devc++内部包含了g++/gcc/c++等等,这些都是编译器,可以在devc++的安装目录里找到,如图
其实编译器就是一个可以运行的程序,它接受你的源代码作为输入,然后输出的就是它的翻译结果啦~~
但是呢,编译器小姐姐是傲娇属性爆棚的那种人~一旦你的源代码中有语法错误,她就不会给你翻译(编译),但是小姐姐人辣么好,她会把你的错误之处向你指出。
所以学习看编译信息就是和小姐姐交朋友的第一步啦~如果你哪个编译信息看不懂,可以把它丢到搜素引擎里去搜搜,一般来说看懂了就能知道哪儿出错了。
而今天的主题是,这种编译错误是什么意思,然后要如何解决这个问题。
泥萌回忆一下,在学着把代码拆分到不同文件里然后用include合并到一起之前是不是从来没见过这种错误呢?
include的作用其实非常简单,就是把你include的文件内容替换你的include那句语句。这也就解释了为何不能A include B然后B include A,想啊,这样替换下去不就无限循环了嘛;以及为什么不能多次include同一个文件,想啊,这不就相当于你的程序里可能会出现两个一毛一样的函数、变量嘛。
这一替换是在编译之前发生的,所以小姐姐在编译时就可以找到你定义在其他文件(file2.cpp)里的函数,从而允许你在当前文件里使用(file1.cpp)。
这本来是极其愉快而简单的一件事,可是泥萌的助教小姐姐不让泥萌include cpp文件。
因为啊,通常来时被incude的叫“头文件”,而头文件一般包含的是类的定义、extern变量声明和函数的声明等等声明性、定义性的东西,而不是具体实现,这样会带来两个显著的好处:
请泥萌仔细地看一下第二点,然后我来解释一下为什么头文件不应该包含具体实现。
一般具体实现放在cpp文件里,这也是为何我们称后缀为.h的文件为头文件而不叫.cpp文件头文件。
假设你修改了某个函数的具体实现,那么显然,包含了这个修改的文件必须重新编译对吧,因为你会include cpp文件,那么include了这个cpp文件的文件也得重新编译,假设还有其他文件include你include这个cpp文件的cpp文件,这个文件也得重新编译,再假设...
这样的话第二点的存在意义在哪??
解决方案就存在于被include的头文件只应该包含声明和定义。
但是如果只包含只有声明文件的头文件,会发生什么呢?
会发生——小姐姐虽然找得到函数的声明,但是她找不到函数的实现!这就是造成文前那个问题的元凶!
let‘s take a closer look on what 小姐姐 has said.
undefined reference to ‘YourFunction‘
请大家体会一下undeclared(声明)和undefined(定义)的区别!
让我来画个图:
(箭头的意思代表include)
小姐姐看到你让她帮你编译一下main.cpp,于是她在编译开始前把declare.h放到main.cpp里。
一切看起来都非常和谐,因为一切在main.cpp中调用的函数、使用的自定义变量类型的声明都可以找到~
小姐姐极其开心呐~
但是当小姐姐开始编译时,听听她怎么说:“伦家当场就懵逼了好嘛qaq”
因为她找不到你函数的实现呐,你函数的实现在define.cpp里,这件事情她怎么可能会知道呢?
除非你告诉她。
所以解决方案其实非常简单,修改你的编译命令,把define.cpp的所在告诉泥萌可怜的小姐姐!
好的,我忘记先向泥萌解释编译命令是啥了。
编译命令就是你告诉小姐姐应该按照什么样的顺序、什么样的方式、什么样的程度来进行编译,要知道其实虽然一直把编译比作翻译,其实编译过程有很多个部分,请参考reference中的Linux GCC常用命令
具体要如何修改呢?如果你是面向命令行编程(虽然我觉得。。泥萌目前大概是不会面向命令行编程的),只需要修改一下编译命令即可:g++ main.cpp define.cpp -o main.exe
这个命令(原来是g++ main.cpp -o main.exe,注意区别)就告诉编译器小姐姐,我还有一个define.cpp文件,如果你需要找某些函数的实现,你可以考虑一下看看define.cpp里面有没有对应的实现~
但是要如何才能直接把你的编译命令告诉编译器小姐姐呢?
follow the instructions,老司机要发车啦~
ctrl+c复制一下。
把这个路径添加到系统变量path里去,具体看http://jingyan.baidu.com/article/8ebacdf02d3c2949f65cd5d0.html
添加之后,再从第一步开始,你就会发现小姐姐对你的召唤有反应了!!
写到这里,我提供了一个解决方案,就是手动写编译命令,告诉小姐姐编译时去考虑define.cpp,在具体情况下,比如泥萌的作业,你要把median.cpp student_info.cpp fails_list.cpp等等放到编译命令里去再编译。
写这篇文章的意义就达成了。
但我还是想多说一些导向性的东西,比起这些东西,技术细节其实并不重要。
大概写了三个小时。。第一次写这种东西。。希望对大家有点帮助吧,写模电作业去qaq。。。我的周末。。真是充实呐苦笑。。
reference(further reading materials!):
C++文件包含处理#include http://c.biancheng.net/cpp/biancheng/view/148.html
C++中头文件(.h)和源文件(.cpp)都应该写些什么 http://blog.csdn.net/lyanliu/article/details/2195632
C++编译链接过程 http://blog.csdn.net/edisonlg/article/details/7081357
Linux GCC常用命令 http://www.cnblogs.com/ggjucheng/archive/2011/12/14/2287738.html
http://man.linuxde.net/gcc
标签:com median 声明和定义 编译链接 处理 bin ext 不同 注意
原文地址:http://www.cnblogs.com/ichn/p/6684819.html