Where should #include be indicated?

As a returning newbie in C ++, I am trying to sort the #include methodology.

I follow a specific set of guides, which I describe in detail below in the following example. So far this has worked for me (the whole project keeps compiling :)), but I'm worried that in the future I may run into problems, so my questions - is this the correct methodology? Is there a better one? What basic logic explains this?

Consider the following example:

Father.h

#pragma once class Father { // Some implementation }; 

ClassA.h

 #pragma once #include "Father.h" #include "StructC.h" class ClassB; class ClassA : public Father { StructC struct_c_obj; ClassB class_b_obj; // Some implementation }; 

ClassA.cpp

 #include "Father.h" #include "ClassB.h" #include "StructC.h" // Some implementation 

ClassB.h and ClassB.cpp
Class does not include

StructC.h

 struct StructC { // Some implementation }; 

I follow these recommendations:

  • All * .h are headed by #pragma once
  • If ClassA inherits from the Father class, it must include it in both * .h and * .cpp files
  • If ClassA uses ClassB (and has a ClassB variable declared in the class scope), it has a class ClassB; declaration of class ClassB; in ClassA.h and #include "ClassB.h" in ClassA.cpp
  • If ClassA uses StructC (and has a StructC variable declared in the class scope), it must include it in both ClassA.h and ClassA.cpp
  • If ClassA uses ClassD or StructE, but only in the ClassA.cpp file, then it should include them only there

This is probably a clumsy set of recommendations with a little understanding of the basic logic, so I'm probably going to get some anger ... Bring it, I'm am trying to find out here ... :)

UPDATE:

  • As some of them are written below, I have an error in the example - you can use forward ClassB declaration in ClassA only if ClassA has a pointer or a reference to ClassB, and not if it has a simple ClassB data element.
+4
source share
5 answers

These are the recommendations that I personally adhere to:

  • Prefer forward ads instead of including when possible. In your case, ClassA contains ClassB , so #include "ClassB.h" is required. If the ClassB type is displayed only in the file by pointer or link, then a direct link would be enough
  • Make the header file "self-sufficient": compilation should never depend on the order of inclusions, and the included file should include / forward declare everything that needs to be analyzed
  • To ensure compliance with the previous rule, always include ClassA.h first in ClassA.cpp and use random ordering for the following: (I use alphabetical sorting)

Regarding other aspects:

  • #pragma is non-standard, prefer to enable guards
  • Keep in mind that you should never forward standard type declarations: if std::string appears in your header file, you must #include <string>
  • If you end up with a header file that includes a million other files, you can look in the pimpl idiom to reduce dependencies (this article also contains several other recommendations regarding header files).
+9
source

#pragma once is non-standard (but widely supported), so you may / may not want to use #ifdef guards.

As for whether or not you #include any particular header, it depends. If the code only requires a forward declaration, be sure to avoid importing by simply declaring it.

And with the exception of the template material, I think it is probably not very convenient to place long function definitions in header files.

Having said that, I think that ClassA.h should actually include ClassB.h , because any user from ClassA.h (presumably to use ClassA ) should have ClassB.h . Well, if he does something like highlighting him.

+1
source

Do not use a ClassB forward declaration when ClassA has a data member of this type. This is normal to use if it has pointers to ClassB, as in:

 #pragma once #include "Father.h" #include "StructC.h" class ClassB; class ClassA : public Father { StructC struct_c_obj; ClassB *class_b_obj; // Some implementation }; 
+1
source

One thing I got from Python (because it is an absolute requirement) is to "import (include) it into the modules in which you use it." This will not allow you to get rid of the problems associated with the presence or absence of definitions.

0
source

Usually I do not use pragma once because pragmas are not standard. You may need to port your code to another compiler where it is not defined, and you will have to rewrite each with #ifndef ... #define idiom.

This is because I'm going straight from #ifndef ... #define .

The second thing: using many inclusions in the header file is not a good idea: I always try to minimize them. If you have too many of them, every time you change a little thing in one of them, you will have to recompile each dependent .cpp file.

If so, I accept the Pimpl idiom, which you can find here here (see C ++ example). In any case, if the size of the project is not so large, I think your approach is correct.

0
source

All Articles