在使用C++时,我们经常可以看到这样一个头文件。
ifndef CLASS_Hdefine CLASS_H//blah blah blahendif
比如说我们有一个main.cpp
,class.h
,和class.cpp
。为什么我们不把class.h
中的内容放到main.cpp
里呢?
首先简单地从编译原理的各个流程上面去看:
- 预处理:预处理器解析以#开头的行的所有源代码,并执行指令。在上面的例子中,文件class.h的内容将插入在include class.h行的位置。考虑到可能会在头文件中的多个位置包含该文件,使用ifndef子句可以避免重复的声明错误。
Once the header is included, it checks if a unique value (in this case CLASS_H) is defined. Then if its not defined, it defines it and continues to the rest of the page. When the code is included again, the first ifndef fails, resulting in a blank file. That prevents double declaration of any identifiers such as types, enums and static variables.
2. 编译:编译器现在可以将所有预处理的源代码文件转换为二进制目标文件。
3. 链接:链接器将目标文件链接在一起。A reference to your class or one of its methods (which should be declared in class.h and defined in class.cpp) is resolved to the respective offset in one of the object files. I write one of your object files since your class does not need to be defined in a file named class.cpp, it might be in a library which is linked to your project.
总的来说,声明可以通过头文件共享,然而把声明链接到类的实现还是通过链接器进行的。
In summary, the declarations can be shared through a header file, while the mapping of declarations to definitions is done by the linker.
更详细地说:
这是一种防止多次包含头文件的预处理器技术。
由于各种原因,头文件可能会出现问题。在项目编译期间,通常会编译每个.cpp文件。简单来说,这意味着编译器将获取您的.cpp文件,打开包含在其中的所有文件,将它们全部连接成一个大文本文件,然后执行语法分析,最后将其转换为一些中间代码,进行优化/执行其他任务,最后生成目标体系结构的程序集输出。因此,如果一个文件被多次包含在一个.cpp文件下,则编译器会将其文件内容添加两次,因此,如果该文件中包含定义,则会出现编译器错误,提示您重新定义了一个变量。当文件在编译过程中由预处理器步骤处理时,第一次到达其内容时,前两行将检查是否已为预处理器定义了CLASS_H。如果没有,它将定义CLASS_H并继续处理它与endif指令之间的代码。下一次预处理器看到文件的内容时,对FILE_H的检查将为false,因此它将立即向下扫描到endif并在此之后继续。这样可以防止重新定义错误。
进一步探究C++头文件的作用
作为一般惯例,在C++编程中,我们将开发分为两种文件类型。一个是扩展名.h,我们称其为头文件。它们通常提供函数,类,结构,全局变量,typedef,预处理宏和定义等的声明。基本上,它们只是为您提供有关代码的信息。然后,我们有了.cpp扩展名,我们称其为代码文件。这将为这些函数,类成员,任何需要定义的结构成员,全局变量等提供定义。因此.h文件声明代码,而.cpp文件实现该声明。因此,我们通常在编译过程中将每个.cpp文件编译为一个对象,然后链接这些对象(因为您几乎看不到一个.cpp文件包含另一个.cpp文件)。
如何解决这些外部问题是链接器的工作。当编译器处理main.cpp时,它通过包含class.h来获取class.cpp中的代码声明。它只需要知道这些函数或变量的外观(这就是声明为您提供的外观)。因此它将main.cpp文件编译为某个目标文件(称为main.obj)。同样,class.cpp被编译成class.obj文件。为了生成最终的可执行文件,将调用链接器以将这两个目标文件链接在一起。对于任何未解析的外部变量或函数,编译器将在存根位置放置一个存根 (For any unresolved external variables or functions, the compiler will place a stub where the access happens.)。然后,链接器将使用此存根,并在另一个列出的目标文件中查找代码或变量,如果找到了该链接,则它将来自两个目标文件的代码合并到一个输出文件中,并将存根替换为函数的最终位置或多变的。这样,如果且仅当在class.h中声明了它们时,main.cpp中的代码才能调用函数并在class.cpp中使用变量。
参考:
https://stackoverflow.com/questions/1653958/why-are-ifndef-and-define-used-in-c-header-files
声明:本文部分素材转载自互联网,如有侵权立即删除 。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别
丞旭猿论坛
暂无评论内容