为什么在.h文件中使用#ifndef CLASS_H和#define CLASS_H,而不是在.cpp中使用? [英] Why use #ifndef CLASS_H and #define CLASS_H in .h file but not in .cpp?

查看:140
本文介绍了为什么在.h文件中使用#ifndef CLASS_H和#define CLASS_H,而不是在.cpp中使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直看到人写的



class.h

  #ifndef CLASS_H 
#define CLASS_H

// blah blah blah

#endif

问题是,为什么不为包含类函数定义的.cpp文件这样做?



假设我有 main.cpp main.cpp 包括 class.h class.h 文件不会导入任何内容,因此 main.cpp 如何知道 class.cpp

解决方案

首先, >

当您在 .h 文件中看到此信息时:

  #ifndef FILE_H 
#define FILE_H

/ * ...这里的声明等... * /

#endif

这是一个预处理器技术,可以防止头文件被多次包含,这可能由于各种原因而有问题。在编译项目期间,通常会编译每个 .cpp 文件。简单来说,这意味着编译器将接受您的 .cpp 文件,打开任何文件 #included ,将它们连接成一个大文本文件,然后执行语法分析,最后将它转换为一些中间代码,优化/执行其他任务,最后生成目标体系结构的汇编输出。因为这个原因,如果一个文件 #included 多次在一个 .cpp 文件下,编译器将附加它的文件内容两次,是该文件中的定义,您将得到一个编译器错误,告诉您重新定义了一个变量。当编译过程中的预处理器步骤处理文件时,首次到达其内容时,前两行将检查是否为预处理器定义了 FILE_H 。如果没有,它将定义 FILE_H 并继续处理它和 #endif 指令之间的代码。下一次预处理器看到该文件的内容时,对 FILE_H 的检查将为false,因此它将立即扫描到 #endif 并继续之后。



在C ++编程中,作为一般惯例,将开发分为两种文件类型。一个是扩展名为 .h ,我们将其称为头文件。它们通常提供函数,类,结构,全局变量,typedef,预处理宏和定义等的声明。基本上,他们只是提供你的代码信息。然后,我们有 .cpp 扩展名,我们称之为代码文件。这将为这些函数,类成员,任何需要定义的结构成员,全局变量等提供定义。因此, .h 文件声明代码, .cpp 文件实现该声明。为此,我们通常在编译期间将每个 .cpp 文件编译为对象,然后链接这些对象(因为您几乎从不会看到 .cpp 文件包含另一个 .cpp 文件)。



这些外部解析是链接器的工作。当您的编译器处理 main.cpp 时,它会通过包含 class.h 来获取 class.cpp 中的代码的声明。它只需要知道这些函数或变量是什么样子(这是一个声明给你)。因此,它会将 main.cpp 文件编译成某个对象文件(称为 main.obj )。类似地, class.cpp 被编译为 class.obj 文件。为了产生最终的可执行文件,调用链接器将这两个目标文件链接在一起。对于任何未解析的外部变量或函数,编译器将放置访问发生的存根。然后链接器将获取这个存根,并在另一个列出的对象文件中查找代码或变量,如果找到,它将来自两个对象文件的代码合并到一个输出文件中,并将存根替换为函数的最终位置,变量。这样,您在main.cpp中的代码就可以在 class.cpp 中调用函数并使用变量,只有在 class.h 中声明它们。



我希望这是有帮助的。


I have always seen people write

class.h

#ifndef CLASS_H
#define CLASS_H

//blah blah blah

#endif

The question is, why don't they also do that for the .cpp file that contain definitions for class functions?

Let's say I have main.cpp, and main.cpp includes class.h. The class.h file does not import anything, so how does main.cpp know what is in the class.cpp?

解决方案

First, to address your first inquiry:

When you see this in .h file:

#ifndef FILE_H
#define FILE_H

/* ... Declarations etc here ... */

#endif

This is a preprocessor technique of preventing a header file from being included multiple times, which can be problematic for various reasons. During compilation of your project, each .cpp file (usually) is compiled. In simple terms, this means the compiler will take your .cpp file, open any files #included by it, concatenate them all into one massive text file, and then perform syntax analysis and finally it will convert it to some intermediate code, optimize/perform other tasks, and finally generate the assembly output for the target architecture. Because of this, if a file is #included multiple times under one .cpp file, the compiler will append its file contents twice, so if there are definitions within that file, you will get a compiler error telling you that you redefined a variable. When the file is processed by the preprocessor step in the compilation process, the first time its contents are reached the first two lines will check if FILE_H has been defined for the preprocessor. If not, it will define FILE_H and continue processing the code between it and the #endif directive. The next time that file's contents are seen by the preprocessor, the check against FILE_H will be false, so it will immediately scan down to the #endif and continue after it. This prevents redefinition errors.

And to address your second concern:

In C++ programming as a general practice we separate development into two file types. One is with an extension of .h and we call this a "header file." They usually provide a declaration of functions, classes, structs, global variables, typedefs, preprocessing macros and definitions, etc. Basically, they just provide you with information about your code. Then we have the .cpp extension which we call a "code file." This will provide definitions for those functions, class members, any struct members that need definitions, global variables, etc. So the .h file declares code, and the .cpp file implements that declaration. For this reason, we generally during compilation compile each .cpp file into an object and then link those objects (because you almost never see one .cpp file include another .cpp file).

How these externals are resolved is a job for the linker. When your compiler processes main.cpp, it gets declarations for the code in class.cpp by including class.h. It only needs to know what these functions or variables look like (which is what a declaration gives you). So it compiles your main.cpp file into some object file (call it main.obj). Similarly, class.cpp is compiled into a class.obj file. To produce the final executable, a linker is invoked to link those two object files together. For any unresolved external variables or functions, the compiler will place a stub where the access happens. The linker will then take this stub and look for the code or variable in another listed object file, and if it's found, it combines the code from the two object files into an output file and replaces the stub with the final location of the function or variable. This way, your code in main.cpp can call functions and use variables in class.cpp IF AND ONLY IF THEY ARE DECLARED IN class.h.

I hope this was helpful.

这篇关于为什么在.h文件中使用#ifndef CLASS_H和#define CLASS_H,而不是在.cpp中使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆