Click here to Skip to main content
Click here to Skip to main content

Tagged as

Improve compile times with forward declarations

, 2 Mar 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
Header files often #include lots of other headers because other classes are being referenced. These chained includes force the compiler to repeatedly load and precompile long lists of headers over and over again. Thanks to #pragma directives or #ifdef guards this is a rather cheap operation,...
Header files often #include lots of other headers because other classes are being referenced. These chained includes force the compiler to repeatedly load and precompile long lists of headers over and over again.
 
Thanks to #pragma directives or #ifdef guards this is a rather cheap operation, but it would be a lot cheaper if the compiler didn't even have to check in the first place: because whenever a header changes, every file that inlcudes that header, or a header that includes that header, or a header that includes a header that... (you get the picture) - the compiler will then be forced to recompile that file - even though there may be not a single actual change regarding that file!
 
For that reason, use forward declarations in headers instead of #includes, whenever you can!
 
Here is an example:
 
File A.h:
#pragma once
class A {
private:
   int m_var1;
   double m_var2;
public:
   void do_something();
}
File Bad.h:
#pragma once
#include "A.h"
class B {
private:
   A* m_var1;
public:
   void work();
}
File Bad.cpp:
#include "Bad.h"
void B::work()
{
   m_var1->do_something();
}
 
When you look at this example, what will happen when the designer for class A decides he needs another method void do_sth_else() for whatever purpose, which class B isn't even interested in? When you compile your project, the compiler will recognize the dependcy of Bad.cpp to Bad.h, which didn't change, but also the dependency of Bad.h to A.h, which did! So it recompiles Bad.cpp, even though nothing has changed with respect to class B!
 
What's even worse, consider class C:
 
File C.h:
#pragma once
#include "Bad.h"
class C
{
private:
   B* m_var1;
public:
   void foo();
}
File C.cpp:
#include "C.h"
void C::foo()
{
   m_var1->work();
}
 
File C.cpp is indirectly dependent on A.h as well, so needs to be recompiled, even though it cannot even directly access B's data member that uses the type!
 
Now change the declaration and definition of class B like that:
 
File Good.h:
#pragma once
class A; // forward declaration!
class B {
private:
   A* m_var1;
public:
   void work();
}
File Good.cpp:
#include "Good.h"
#include "A.h" // include moved from header to source file
void B::work()
{
   m_var1->do_something();
}
 
If the designer of class A now decides to change the interface of class A, Good.cpp will still need to be recompiled (because it now directly includes A.h - but that cannot be avoided). But file C.cpp remains untouched: it no longer has any direct or indirect dependency to class A and thus does no longer require to be recompiled!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Stefan_Lang
Software Developer (Senior)
Switzerland Switzerland
Graduated at TU Darmstadt in Math & CS, with a heavy focus on CAD/CAM
 
Programming and designing applications in C++ in the areas AI, real-time programming, client-server applications and CAD/CAM since 1985.
 
Personal interests: AI, computer graphics, games, reading

Comments and Discussions

 
GeneralMy vote of 1 PinmemberYoldas Askan15-Sep-14 8:02 
GeneralReason for my vote of 3 Good Example! PinmemberDilip Jaju (DJ)25-Aug-11 0:57 
Reason for my vote of 3
Good Example!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411028.1 | Last Updated 2 Mar 2010
Article Copyright 2010 by Stefan_Lang
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid