Search code examples
c++includemethodology

Where should #include statements reside?


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

I'm following a certain set of guidelines I detail below the following example. So far this has worked out for me (the entire project keeps compiling :) ), but I'm worried I may encounter problems in the future, therefore my questions are - is this a correct methodology? Is there a better one? What's the underlying logic that explains it?

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
A class without includes

StructC.h

struct StructC {
    // Some implementation
};

I follow these guidelines:

  • All *.h are headed by a #pragma once declaration
  • If ClassA inherits from class Father, it must include it in both *.h and *.cpp file
  • If ClassA uses ClassB (and has a ClassB variable declared at the class's scope), it has a class ClassB; decleration in ClassA.h and an #include "ClassB.h" in ClassA.cpp
  • If ClassA uses StructC (and has a StructC variable declared at the class's scope), it has to 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 guidelines with little understanding of the underlying logic, so I'm probably going to get some wrath... Bring it on, I am trying to learn here... :)

UPDATES:

  • As some have written below, I have an error in the example - you can use a forward declaration of ClassB in ClassA only if ClassA has a pointer or a reference to ClassB and not if it has a simple ClassB data-member.

Solution

  • These are the guidelines I personally follow :

    • Prefer forward declarations instead of includes whenever possible. In your case, ClassA contains a ClassB so a #include "ClassB.h" is required. Had the ClassB type only appear in the file by pointer or reference, a forward reference would have been sufficient
    • Make header file "self sufficient" : compilation should never depend on the order of inclusions, and an include file should include / forward declare all it needs to be parsed
    • To ensure that the preceding guideline is respected, always include ClassA.h first in ClassA.cpp, and use an arbitrary ordering for the following includes (I'm using alphabetical sort)

    Regarding other aspects :

    • #pragma is non standard, prefer include guards
    • Keep in mind that you should never forward declare standard types : if std::string appears in your header file, you have to #include <string>
    • If you end up with a header file which includes a million other files, you might want to look into the pimpl idiom to reduce dependencies (this article also contains several other guidelines regarding header files).