Is there any materials about how to use #include crorrectly? I didn't find any c/c++ text book that explain this usage in details. In formal project, I always get confused in dealing with it. Thanks for your help.
The big one that always tripped me up was this:
This searches in the header path:
#include <stdio.h>
This searches in your local directory:
#include "myfile.h"
Second thing you should do with EVERY header is this:
myfilename.h:
#ifndef MYFILENAME_H
#define MYFILENAME_H
//put code here
#endif
This pattern means that you cannot fall over on redefining the headers in your compilation (Cheers to orsogufo for pointing out to me this is called an "include guard"). Do some reading on how the C compiler actually compiles the files (before linking) because that will make the world of #define and #include make a whole lot of sense to you, the C compiler when it comes to parsing text isn't very intelligent. (The C compiler itself however is another matter)
- Check Large-Scale C++ Software Design from John Lakos if you have the money.
- Google C++ coding guidelines also have some OK stuff.
- Check Sutter Herb materials online (blog) as well.
Basically you need to understand where include headers are NOT required, eg. forward declaration. Also try to make sure that include files compiles one by one, and only put #includes in h files when it's a must (eg. templates).
Header files are C's way of separating interface and implementation. They are divided into two types: standard and user-defined header files. A standard header file, such as string.h, allows us access to the functionality of an underlying C library. You should #include it in every .c file which uses the relevant functionality. Usually this uses brackets as in #include A user-defined header file exposes your implementation of functions to other programmers or other parts of your C code. If you have implemented a module called rational.c for calculations with rational numbers, it should have a corresponding rational.h file for its public interface. Every file which uses the functionality should #include rational.h, and also rational.c should #include it. Usually this is done using #include "rational.h" The part of compilation which does the #includes is called the C preprocessor. It mostly does text substitutions and pastes text. Spence is correct in his pattern for preventing duplicate #includes, which mess up the namespace. This is the base of inclusion, GNU Make gives you lots more power, and lots more trouble as well.
You use #include "yourfile.h" if yourfile.h is in the curent working directory
and #include if the path to yourfile.h file was included in the c++ include Directories (somewere in configuration, example: c:\mylib\yourfile.h , the path c:\mylib\ has to be specified as an include directory)
Also you can include .cpp and .hpp (h plus plus).
There a particular set of files that can be writen like: #include . For this to particular example work you need to specify using namespace std;
There is a very nice software that is integrated with microsoft's visual c++ , and shows the include paths. http://www.profactor.co.uk/includemanager.php
In addition to the other comments, remember that you don't need to #include a header in another header if you only have a pointer or reference. E.g.:
Header required:
#include "Y.h"
class X
{
Y y; // need header for Y
};
Header not required:
class Y;
class X
{
Y* y; // don't need header for Y
};
//#include "Y.h" in .cpp file
The second example compiles faster and has less dependencies. This can be important in large code bases.
check out the discussion on using #include<filename.h> #include<filename>
for c++ includes of c libraries
Edit: Andy Brice also made this point in a briefer way.
Folling up in null's answer, the most important thing to think about is where you put your #include's.
When you write a #include the preprocessor literally includes the contents of the file you list in the current file, including any #includes in those files as well. This can obviously lead to very large files at compile time (coad bloat) so you need to consider carefully if an #include is needed.
In a standard code file layout where you have a .h file for a class with the class and function declarations, and then a .cpp implementation file, you should be be careful of the number of #includes that go in the header file. This is because, every time you make a change to the header file, any files that also include it (ie. that use your class) will also have to be recompiled; if the header itself has lots of includes then every file that uses the class gets bloated significantly at compile time.
It is better to use forward declarations where possible, so that you can write the method signatures etc. and then #include the relevant files in the .cpp file so that you can actually use the classes and structures that your code depends on.
//in myclass.h
class UtilClass; //forward declaration of UtilClass - avoids having to #include untilclass.h here
class MyClass
{
MyClass();
~MyClass();
void DoSomethingWithUtils(UtilClass *util); //this willcompile due toforward declaration above
};
//then in the .cpp
#include utilclass.h
void MyClass::DoSomethingWithUtils(UtilClass *util)
{
util->DoSomething(); //this will compile because the class definition is included locally in this .cpp file
}
So your compiler may support 2 unique search paths for include files:
Informally we could call the system include path and the user include path.
The #include <XX> searches the system include path.
The #include "XX" searches the user include path then the system include path.
Checking the draft standard n2521:
Section 16.2:
2 A preprocessing directive of the form
# include < h-char-sequence> new-line
searches a sequence of implementation-defined places for a header identified
uniquely by the specified sequence between the < and > delimiters, and
causes the replacement of that directive by the entire contents of the
header. How the places are specified or the header identified is
implementation-defined.
3 A preprocessing directive of the form
# include " q-char-sequence" new-line
causes the replacement of that directive by the entire contents of the
source file identified by the specified sequence between the " " delimiters.
The named source file is searched for in an implementation-defined manner.
If this search is not supported, or if the search fails, the directive is
reprocessed as if it read
# include < h-char-sequence> new-line
with the identical contained sequence (including > characters, if any)
from the original directive.
An example of this would by gcc
-isystem <dir> Add <dir> to the start of the system include path
-idirafter <dir> Add <dir> to the end of the system include path
-iwithprefix <dir> Add <dir> to the end of the system include path
-iquote <dir> Add <dir> to the end of the quote include path
-iwithprefixbefore <dir> Add <dir> to the end of the main include path
-I <dir> Add <dir> to the end of the main include path
To see where your gcc is searching do this:
g++ -v -E -xc++ /dev/null -I LOOK_IN_HERE
#include "..." search starts here:
#include <...> search starts here:
LOOK_IN_HERE
/usr/include/c++/4.0.0
/usr/include/c++/4.0.0/i686-apple-darwin9
/usr/include/c++/4.0.0/backward
/usr/local/include
/usr/lib/gcc/i686-apple-darwin9/4.0.1/include
/usr/include
/System/Library/Frameworks (framework directory)
/Library/Frameworks (framework directory)
End of search list.
So how do you use this knowledge.
There are several school of thought. But I always list my libraries from most specific to most general.
Example
File: plop.cpp
#include "plop.h"
#include "plop-used-class.h"
/// C Header Files
#include <stdio.h> // I know bad example but I drew a blank
/// C++ Header files
#include <vector>
#include <memory>
This way if the header file "plop-used-class.h" should have included <vector> this will be cought by the compiler. If I had put the <vector> at the top this error would have been hidden from the compiler.
Just an addendum to Andy Brice's answer, you can also make do with forward declarations for function return values:
class Question;
class Answer;
class UniversityChallenge
{
...
Answer AskQuestion( Question* );
...
};
Here's a link to a question I asked a while back with some good answers http://bytes.com/groups/c/606466-forward-declaration-allowed.