Why Use #Ifndef Class_H and #Define Class_H in .H File But Not in .Cpp

Why use #ifndef CLASS_H and #define CLASS_H in .h file but not in .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.

Why are #ifndef and #define used in C++ header files?

Those are called #include guards.

Once the header is included, it checks if a unique value (in this case HEADERFILE_H) is defined. Then if it's 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.

My class, defined in a .h file, is not found by the .cpp file

When using precompiled headers #include "stdafx.h" must appear before every #include in every file. Otherwise the preprocessor/compiler will ignore the other files. You can read more about how to use precompiled headers here. The other option is just not use them if you don't need the improved compilation time.

Some unrelated notes about your code: this is pointer to the current object, so you cannot access properties from it with the dot . operator(which is used for objects with class type, not pointer). You have to use ->. For example this->visibility or if it is unambiguous just visibility. Also since you have dynamic memory allocation with new you have to have a destructor that calls delete. But in this particular case new is not needed and you can just let the vector manage the memory itself by making it a vector variable and not a pointer and not defining it with new.

#ifndef not letting my files see what's in the header (C++)

just #include "node.h" and make sure to compile all cpp files

Why are .h files included in .cpp files and not vice versa?

This seems to be the right etiquette anyway.
It's not a matter of etiquette, but .cpp files are considered as translation units and handled as such by any decent compiler or build system.

The .h files contain all the declarations needed to be seen for use in other translation units.

The compiled .cpp files are stitched together in the final linking phase.

This way though, I'm not including the .cpp file anywhere, and currently my code is complaining about not finding the functions therein. What am I doing wrong?

You probably missed to get that last part of linking the generated object files right.


As for your edit:

You're showing a template declaration now, which is a more special case. The compiler needs to see the template definitions to get them instantiated correctly.

You can read more about the details here: Why can templates only be implemented in the header file?

class not declared in scope - even though .h was included

The common circular include problem occurs with:

a.h

#ifndef A_H
#define A_H
#include "b.h"
// do something requiring content from b.h
#endif

b.h

#ifndef B_H
#define B_H
#include "a.h"
// whatever
#endif

If some cpp includes "a.h" you might get away with it (if b.h didn't really need a.h). But if that cpp instead includes b.h then b.h includes a.h BEFORE declaring things needed by a.h. Then a.h tries to include b.h but the include guard blocks that, so the compiler processes a.h without the declarations from b.h and fails.

That common problem is often masked by another layer, as it was in your example: todoitem.h included "todolist.h", even though it didn't really need it, then "todolist.h" included "intemmonitor.h" which needed "todoitem.h" but failed to include it due to the include guard.



Related Topics



Leave a reply



Submit