@Oluseyi: you are right. As a professor told me some years ago, the devil lies (always) in the details, and the one who forget to consider the details is a fool. In this case, I used an imprecise terminology in order to give a somewhat precise definition of two important words, and I forgot to explain the details. My bad. Apologies to everyone.
Quote:
Original post by adam23
I have one question about your post before Emmanuel. You have three files, main.ccp, file.h, and file.cpp.
I was wondering what the recommended way to include files is especially if you have a lot of files.
//Lets say I have a main.h
*** Source Snippet Removed ***
Then my main.cpp would look like this
*** Source Snippet Removed ***
Now lets take and say file.cpp
I usually do it this way so I have access to all other included files.
*** Source Snippet Removed ***
I've found that this prevents a lot of my preprocessor errors. The main thing I have found is that the order they are included matters, but I have never had any other problems doing it this way. I typed this in here, so there may be some errors, but I hope you understand my question. In file.h I wouldn't have any includes.
What I think is happening is that the declaration for file.h is being posted in main, then all of that is being posted in file because of the include in file.
You can verify your assumption using the "/P /EP" technique that I described earlier. But if by main you intended to write main.h then your are technically right: everything in main.h will be copied file.cpp, and since everything in file.h is 'copied' in main.h, then you'll have everything you need in the preprocessed file.cpp.
However, the question you ask is not an easy one. I have to quit the field of pure C++ programming to enter the large field of software engineering to give your the beginning of an answer.
In order to be efficient (as in "I type less thus I have fewer possible bugs"), you'd better try to limit your #include directives to what's really needed. Moreover, it is a good practive to always include file.h in file.cpp (if file.cpp implements what's declared in file.h) even if another file included in file.cpp already includes file.h. The main reason behind this is that the object oriented paradigm tells you that while the implementation of a class might change, tghe interface of this class is less subject to changes than its implementation. In C++, header files do more than describing an interface - they also describe the private part of a class, and that's part of the implementation. It means that whenever you change the implementation of a particlar class, you might also change the header file for this class.
On day D, you class A is using class B internally (for example, a private member of A is a B instance). Thus, A.h includes B.h. B.cpp instantiate a A object, so B.cpp is including A.h. You feel it's enough - since A.h includes B.h, you d'ont have to include B.h in B.cpp. Later, (day D+1) you change the implementation of A and you figure out that you don't need to have a member of type B. As a consequence, you remove the #include "B.h" directive from "A.h". Suddenly, B.cpp refuse to compile, despite the fact that you don't change anything in B.cpp.
Remember that you are using header guards in your headers. Those guards avoid multiple inclusions of a header file in a compilation unit (such multiple inclusion might result in multiple declaration of the same symbol, something that a compiler don't like very much). As a consequence, there is no problem to #include "B.h" twice in B.cpp. You can take advantage of this to avoid the error I just explained.
The correct usage of header file is hard, but fortunately, some rules might help:
- The implementation file of a class should explicitely include the file that declare this class (A.cpp always includes A.h).
- The less file you include, the better it is
- The order of the #include directives should not depend on the #included files
- Whenever you use a symbol that is declared in header1.h in another file (either another header file or a cpp file), #include "header1.h" in this file
The benefits of the firt rule is easy to understand: you don't have to search which file really includes the declaration of your class, and you avoid the error I described earlier.
The benefits of the second rule is less visible and has to do with the reduction of dependencies. A file should be included only if there is a direct dependency between the includer and the included file. Since more dependencies means more coupling means a decrease in code reuseability, avoiding dependencies will probably (not always) increase reusability - when it comes to software design, this is considered as a Good Thing.
Be aware that this rule doesn't mean "don't include any header file in your cpp". One big mistake in software design is to create what is called a god class - ie a class that do everything. Of course, it means that this class won't depend on any other class - but it also means that there is no abstraction in your project, and no abstraction leads to no possible reuse. God classes are not OO programming - they are procedural programming in disguise.
The third rule is a bit more complex to understand. The goal is also to ease both core reading and code writing. There is nothing more insane that having to include foo.h before bar.h whenever you want to declare the class "bar". If bar needs to know foo, then, please, include foo.h into bar.h.
The last rule is a temporary one - you'll see that you can bypass it when you'll learn about
forward declarations. For the moment, consider it as an axiom because it is the only way to correctly follow the 3rd rule. The other benefit is that you can know what will be used in a file by reading the list of included files.
Let's implement these rules into a simple example: main.cpp defines main(); main() instantiate class A and class A contains a member of type B. We have 5 files: main.cpp, A.h, A.cpp, B.h, B.cpp.
Rule 1 means that A.cpp always includes A.h and B.cpp includes B.h.
Rule 2 tells you that since B.cpp don't need A.h, you don't have to #include A.h in B.cpp (rather obvious)
Rule 3 means that since a B object is declared in the interface of A, A.h needs to include B.h. If we fail to do this, we have to #include "A.h" whenever we want to use a B object - thus, the #include order matters.
Rule 4 means that since A.h is referencing class B, we need to include B.h in A.h (cool: rule 3 already told us to do so. This is not very important because the reason is very different).
Conclusion:
- main.cpp includes A.h
- B.cpp includes B.h
- A.cpp includes A.h
- A.h includes B.h
In your example, main.cpp includes main.h, main.h includes file.h and file.cpp includes file.h. If file.cpp needs to instantiate (or just need to know) a symbol that is declared in main.h then it should also include main.h.
There is something even less obvious in your example because it introduce something which is called circular dependencies (A depends on B which depends on A). Generally speaking, this is something to avoid. There are some cases where it is difficult to get rid of this circular dependencies but in most situations this is software design mistake.
I won't discuss more about circular dependencies now - experience told me that software design is something that you must learn
later [smile]
I hope I'm clear (and precise enough [smile])
And I added those </li> tags! [smile]