Starting in 1996, Alexa Internet has been donating their crawl data to the Internet Archive. Flowing in every day, these data are added to the Wayback Machine after an embargo period.
In our daily experience, we are making our project in different files, not in a single file. We will do this because we want to reduce the compilation time during the development as well as reuse the code written in different files. For example, let's say that you want to make some project that has 10,000 lines of code. During the development of project, or after it, if we change any single line, the compiler has to recompile all 10,000 lines. With today's computers, it might not be a big problem, but it will eventually become a nightmare when projects become larger. On the other hand, if we split our project into more than one file, such as 10 files each containing 1000 lines, any change in one file ideally should not affect in other files.
It doesn't matter that your Camera class does not include Point.H or ViewPort.H directly; it is included in the Camera translation unit. Now, a change in Point header file will compile not only Camera translation unit, but also all translation units in this example.
The basic rule of thumb to minimize physical dependencies is:
"Try to avoid inclusion of a header file within a header file until you don't have any other option."
But how can we make the compiler happy when we are not including a header file? To see the answer to this question, we first must understand in which cases we are forced to include a header file and in which cases we can avoid it.
You have to include the header file when you need the full details of the class. In other words, you have to include a header file when you are accessing a member function or variable of a class, inherit from a class, or aggregate its object in another class. We have already decided not to write implementation code in a header file, so this first case will be eliminated automatically. If you use another object in member functions only, either creating its local object or use it as a parameter, or it contains a pointer of another class, you do not need to include its header file. To make the compiler happy too, you can just do forward of that class in the header file. Now, we can restate our basic rule to minimize physical dependencies:
"Use a Forward declaration instead of including a header file wherever possible, such as in the case when you are not inheriting a class or aggregating it in another class."
For example, in this case we have to include the Point header file in the ViewPort header file.
#include "Point.h"
class ViewPort
{
public:
// Other functionsprivate:
// other attributes
Point m_PtLeftTop;
Point m_PtRightBottom;
};
But, there is no need to include a ViewPort header file in the Transformation header files if it just uses it. Such as the following:
class ViewPort;
class Transformation
{
public:
void Scale(int p_x, int p_y, ViewPort& p_viewPort);
// other functions
};
But, you have to include the ViewPort header file in the Transformation implementation file because there is no way to avoid this. The situation is a little bit better, and now a change in Point.H will not propagate in all translation units. At least, it will not have any effect on all the translation units that include the Transformation.H file.
You can further reduce the physical dependencies by making a pointer of a class rather than making the object of a class. In the case of a pointer, the compiler does not need full details in header file and it can be totally eliminated.
In this case, you have to create and destroy the object yourself, as well as there is extra overhead of function calling. In addition, this physical design might not fit very well to your logical design because you are not doing inheritance; therefore, you can't access the protected data of a class, and cannot override virtual functions. This technique is also known as the "Pointer to Implementation Principle" or, in short, the "PImpl Principle."
There might be one solution to avoid including a header within a header. Include all header files in the CPP file before including its own header file. Take a look at the above example; ViewPort.H needs the Point.H file. Now, include this header file in ViewPort.CPP before including the ViewPort.H file.
Compilers will look at this translation unit so that it seems to be something like this:
and happily compile this unit. But, there are two problems in this approach. The first is that you have to include header files in the proper order. You have to remember the dependencies of the header file and include it in the proper order or the program will not recompile even if you include all the required header files, but not in proper order. The second problem is even more problematic; if you want to use ViewPort.H in any other translation unit, that translation unit will not compile until you include Point.H. From a physical point of view, you haven't changed anything, but you also create more problems by introducing dependencies among header files; these are hard to remember. Here is one more rule of thumb for managing physical dependencies:
"Never make any files that are dependent on the order of header file inclusion."
About the Author
Master in Computer Science (MCS) getting first class second position from University of Karachi.
Tools:
Add www.codeguru.com to your favorites Add www.codeguru.com to your browser search box IE 7 | Firefox 2.0 | Firefox 1.5.xReceive news via our XML/RSS feed
RATE THIS ARTICLE:
Excellent Very Good Average Below Average Poor
(You must be signed in to rank an article. Not a member? Click here to register)
Latest Comments:
No Comments Posted.
Add a Comment:
Title:
Comment:
Pre-Formatted:
Check this if you want the text to display with the formatting as typed (good for source code)
(You must be signed in to comment on an article. Not a member? Click here to register)