Reputation: 30104
Is there any material about how to use #include
correctly?
I didn't find any C/C++ text book that explains this usage in detail.
In formal project, I always get confused in dealing with it.
Upvotes: 20
Views: 28567
Reputation: 16121
First decide if you need it. From https://cplusplus.com/articles/Gw6AC542/
Upvotes: 0
Reputation: 6107
Is there any material about how to use #include correctly?
I'd strongly recommend section, SF: Source files, of the C++ Core Guidelines as a good starting point.
I didn't find any C/C++ text book that explains this usage in detail.
Much conventional wisdom on the topic of physical composition of C++ projects can likely be found in "Large-Scale C++ Software Design" by John Lakos.
In formal project, I always get confused in dealing with it.
You are in good company. Prior to C++20 modules, #include
was the only practical way to compose C++ translation units from multiple files. It is a simple, limited facility through which the preprocessor essentially copy/pastes entire files into other files. The resultant compiler input is often huge, and work is commonly repeated from one translation unit to the next.
Upvotes: 0
Reputation:
You use #include "yourfile.h"
if yourfile.h
is in the current working directory
and #include <yourfile.h>
if the path to yourfile.h
file was included in the C++ include directories (somewhere 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 is a particular set of files that can be written like: #include <iostream>
. 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
Upvotes: -3
Reputation: 7568
Edit: Andy Brice also made this point in a briefer way.
Following 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 (that is, 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 will compile due to forward 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.
}
Upvotes: 0
Reputation: 47990
Check out the discussion on using #include<filename.h>
and #include<filename>
for C++ includes of C libraries.
Upvotes: 1
Reputation:
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).
Upvotes: 16
Reputation: 264659
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.
Upvotes: 16
Reputation: 8627
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.
Upvotes: 3
Reputation: 2317
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.
Upvotes: 3
Reputation: 29360
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)
Upvotes: 26
Reputation: 20621
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.
Upvotes: 2