What You'll Learn

    • Optimal include ordering
    • Forward declarations to reduce coupling
    • PIMPL idiom for compile firewalls
    • Self-contained header design

    Header File Best Practices

    In large C++ projects, compile times are measured in minutes — sometimes hours. The biggest factor? Headers. Every unnecessary #include cascades through the dependency graph, recompiling hundreds of files when one header changes. This lesson teaches the techniques that keep compile times fast and dependencies clean.

    Include Order — Catch Bugs Early

    Include the corresponding header first (widget.h in widget.cpp). This catches missing includes in the header — if widget.h needs <string> but doesn't include it, putting it first will fail immediately instead of being silently fixed by an earlier include.

    Pro Tip: Use clang-format with IncludeBlocks: Regroup and IncludeCategories to automatically sort and group includes on save.

    Include Order

    Proper header inclusion ordering

    Try it Yourself »
    C++
    #include <iostream>
    #include <string>
    #include <vector>
    #include <memory>
    using namespace std;
    
    // === Include Order Best Practices ===
    // 1. Corresponding header (e.g., widget.h for widget.cpp)
    // 2. C system headers (<cstdio>, <cstring>)
    // 3. C++ standard headers (<iostream>, <vector>)
    // 4. Third-party library headers (boost, fmt, etc.)
    // 5. Your project headers
    //
    // Each group separated by a blank line
    // Alphabetical within each group
    
    // Example for logger.cpp:
    // #include "logger.h"   
    ...

    Forward Declarations — Minimize Dependencies

    If a header only uses a pointer or reference to a type, forward-declare it instead of including its header. This breaks the include chain and prevents recompilation when the forward-declared type's implementation changes.

    Common Mistake: Forward-declaring standard library types (class string;). This is undefined behaviour — only forward-declare your own types or types from libraries that explicitly support it.

    Forward Declarations

    Reduce includes by forward-declaring types

    Try it Yourself »
    C++
    #include <iostream>
    #include <string>
    #include <memory>
    using namespace std;
    
    // Forward declarations reduce #include dependencies
    // Use when you only need a pointer or reference to a type
    
    // === BAD: unnecessary #include ===
    // In renderer.h:
    // #include "texture.h"    ← pulls in ALL of texture's dependencies
    // #include "mesh.h"       ← pulls in ALL of mesh's dependencies
    // class Renderer {
    //     Texture* activeTexture;  ← only need a pointer!
    //     Mesh* currentMesh;       ← only need a 
    ...

    PIMPL — The Ultimate Compile Firewall

    The PIMPL (Pointer to Implementation) idiom hides all private members behind a forward-declared struct. The header contains only a unique_ptr<Impl>. Changing the implementation recompiles only one .cpp file — not every file that includes the header.

    PIMPL Idiom

    Hide implementation details behind a pointer

    Try it Yourself »
    C++
    #include <iostream>
    #include <memory>
    #include <string>
    using namespace std;
    
    // PIMPL (Pointer to IMPLementation) idiom
    // Hides implementation details from the header
    // Reduces compile times and provides ABI stability
    
    // === widget.h (public header) ===
    class Widget {
        struct Impl;                    // forward declare
        unique_ptr<Impl> pImpl;        // only a pointer in header
    public:
        Widget(const string& name, int value);
        ~Widget();                      // must declare (uniqu
    ...

    Quick Reference

    TechniqueCompile Time Impact
    Ordered includesCatches bugs, no speed change
    Forward declarations10-30% faster in large projects
    PIMPLIsolates changes to one .cpp file
    #pragma oncePrevents redundant parsing
    Precompiled headers50%+ faster for heavy STL usage

    Lesson Complete!

    You now know how to organize headers for fast compile times, clean dependencies, and ABI stability.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service