-
Header Files
Posted on March 21st, 2009 1 commentThe physical design of a project is a vast topic, I think it will be useful to suggest some simple practices that will help point you in the right direction when you are just starting a project. They can also be applied to a large project but more care is needed.
The first things you can do:
- Make all headers standalone
- Keep your classes in seperateĀ .hpp and .cpp pairs, aim for one class per file.
- Use precompiled headers as an optimisation technique and nothing more.
- Don’tĀ put using namespace in any of your header files, you’ll pollute the namespace.
- Be careful of templates and where they are defined.
1. Make all header files standalone
One of the most important things you can do upfront, is to make all your headers standalone. By standalone I mean you can #include the header file in an empty .cpp file with no #includes before it and have it compile with no errors.
A header file should not depend on other header files being included before it in a cpp or h file. The advantage of this is that you will now be able to easily move the files between projects and you’ll always know exactly what a class or header file depends on.
2. Keep your classes in seperate .hpp and .cpp pairs, aim for one class per file.
When you define your class, name your files after the class. So if your class is to be called foo. You would create foo.h and foo.cpp. Unless you are using precompiled headers foo.h should always be the first include for the cpp file. This ensures the .h is standalone. Even if all the implementation is in the .h file I still believe it is good practice to make an empty .cpp file and include the .h file into it.
The beginning of foo.cpp should look like:
#include "foo.h"
Alternatively, if you are using precompiled headers based on the stdafx.h file:
#include "stdafx.h" #include "foo.h"
3. Use precompiled headers as an optimisation technique and nothing more
If you want to optimise your build you can put the most commonly included header files like <windows.h> or <vector> into the “stdafx.h” file and then the compiler only has to process those files once per build. However there are some dangers.
I’ve seen projects that use the precompiled header file (Commonly called “stdafx.h” for Visual Studio Projects) as a catch all file for holding any header file that might be used by two or more cpp files. This is dangerous because it encourages the bad practice of having a huge header file that is included in all of the projects files, this huge header file usually includes many (often 100’s) other header files. It’s commonly called “globals.h” or “common.h”. Then it’s usually included in “stdafx.h” or “stdafx.h” itself becomes one of these bloated header files.
I can’t stress enough that you should try to avoid making header files whose only purpose is to include other header files. It’s usually a small step towards the “globals.h” or “common.h” situation. The only exception to this rule is “stdafx.h” and only for optimisation.
Just because files like <windows.h> or <vector> are in “stdafx.h” doesn’t mean that you can leave them out of the cpp files that include “stdafx.h”. If you do, you have lost some dependency information about your cpp file. Instead of knowing that foo.cpp needs <vector> you only know that foo.cpp needs “common.h” or “stdafx.h”, Now the question is, what headers inside these files does foo depend on. This makes it quite difficult to move foo.cpp into another project or a test framework.
I think it’s best to always imagine the “stdafx.h” file as being empty. In fact I think you should have two build configurations, a normal one using precompiled headers and one with an empty “stdafx.h”. That way you can check if you are missing any header dependencies by simply compiling the project with the empty “stdafx.h”.
Note for precompiled headers (at least in the Visual Studio C++) you don’t necessarily have to name the precompiled header file “stdafx.h”, you can change it to anything you want in the project settings. I find it easier just to leave it as the default name that Visual Studio gives you. The name doesn’t really matter since it is just an optimisation technique and not a real part of your project. Never include anything before the precompiled header, it just won’t be processed. Think of #include “stdafx.h” as the beginning of the file. It’s just like the compiler has saved it’s state at the end of stdafx.h and continues where it left off at #include “stdafx.h”.
I’ll talk more about 4, 5 in my next post
One response to “Header Files”
-
Daniel Roberts April 28th, 2009 at 03:58
Very nice. This sums it up well.
Leave a reply


