Why use #ifndef CLASS_H and #define CLASS_H in .h file but not in .cpp?

后端 未结 9 1262
谎友^
谎友^ 2020-12-02 03:30

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

相关标签:
9条回答
  • 2020-12-02 04:07

    That's the distinction between declaration and definition. Header files typically include just the declaration, and the source file contains the definition.

    In order to use something you only need to know it's declaration not it's definition. Only the linker needs to know the definition.

    So this is why you will include a header file inside one or more source files but you won't include a source file inside another.

    Also you mean #include and not import.

    0 讨论(0)
  • 2020-12-02 04:08

    its because of Headerfiles define what the class contains (Members, data-structures) and cpp files implement it.

    And of course, the main reason for this is that you could include one .h File multiple times in other .h files, but this would result in multiple definitions of a class, which is invalid.

    0 讨论(0)
  • 2020-12-02 04:25

    main.cpp doesn't have to know what is in class.cpp. It just has to know the declarations of the functions/classes that it goes to use, and these declarations are in class.h.

    The linker links between the places where the functions/classes declared in class.h are used and their implementations in class.cpp

    0 讨论(0)
  • 2020-12-02 04:26

    It is generally expected that modules of code such as .cpp files are compiled once and linked to in multiple projects, to avoid unnecessary repetitive compilation of logic. For example, g++ -o class.cpp would produce class.o which you could then link from multiple projects to using g++ main.cpp class.o.

    We could use #include as our linker, as you seem to be implying, but that would just be silly when we know how to link properly using our compiler with less keystrokes and less wasteful repetition of compilation, rather than our code with more keystrokes and more wasteful repetition of compilation...

    The header files are still required to be included into each of the multiple projects, however, because this provides the interface for each module. Without these headers the compiler wouldn't know about any of the symbols introduced by the .o files.

    It is important to realise that the header files are what introduce the definitions of symbols for those modules; once that is realised then it makes sense that multiple inclusions could cause redefinitions of symbols (which causes errors), so we use include guards to prevent such redefinitions.

    0 讨论(0)
  • 2020-12-02 04:29

    The CLASS_H is an include guard; it's used to avoid the same header file being included multiple times (via different routes) within the same CPP file (or, more accurately, the same translation unit), which would lead to multiple-definition errors.

    Include guards aren't needed on CPP files because, by definition, the contents of the CPP file are only read once.

    You seem to have interpreted the include guards as having the same function as import statements in other languages (such as Java); that's not the case, however. The #include itself is roughly equivalent to the import in other languages.

    0 讨论(0)
  • 2020-12-02 04:31

    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.

    0 讨论(0)
提交回复
热议问题