Originally Posted by
DoctorX
Hi all-
I’m teaching myself C++ from a textbook and there’s a convention I’m starting to notice that doesn’t make sense to me, and it’s not explained in the book.
When creating a class, the convention seems to be to put the class declaration in a header file and put the member functions in a .cpp file. That part I understand, but the way the files are #included seems strange...
When you include a class definition in a program, you #include the header file for that class, right? But the header file doesn’t #include it’s .cpp counterpart, in fact it seems to be the other way around.
Why is it done this way? Seems like the program file should #include the .cpp file for the class instead of the header file.
The #include statement is a pre-processor directive. When the pre-processor encounters the directive in the compilation unit, it attempts to open the file and locate the contents of the file in place of the directive.
A useful exercise is for you to configure or invoke your build system so that you just run the pre-processor only. Then, review the output that it creates. This will give you a better understanding of how the whole system interacts.
When we write a program, we usually define the class in a separate header. The primary reason for this is so that we can organize the contents of the symbol definitions separately from their implementation. This is because we may want to distribute the headers separately from the compiled object files, since we may want to archive the object files into a library. This is a method of "packaging" the object files so that we can easily distribute several object files in a single library file so that the user of the library needs only to link against the single library file rather than our several (perhaps hundreds!) of object files.
The basic steps of "compiling" even a simple program such as "Hello World" involves running the preprocessor, the compiler and the linker. You should take a closer look at all of the related invocation options for each of these tools as these options give you control over how the tool responds to the provided input.
You can see here that the word "compiling" is a misnomer, since the compilation step is just one of the three basic steps involved.
As you being exploring the world of programming in C++, you will often find the usage of:
#include "somefile.h" --or--
#include <somefile.h>
You may also find that your tools need one of:
#include <iostream> --or--
#include <iostream.h>
In the first case, where the quotation marks are used to include a file, this method of pre-processor directive assigns the responsilibity of managing the location details of file to your code. In the second case, where the "angle brackets" are used to include a file, this method of pre-processor directive assigns the responsibility of managing the location details of the file to your build environment...and is infinitely (but definitely arguably) more representative of professional software developers.
Additionally, if you find that you must use:
#include <iostream.h>
...as opposed to:
#include <iostream>
...your tools are definitely out of date.
Since your head seems to be connecting to the notion of including the .cpp file rather than the .h file, let's touch upon that point for a moment.
Note that we may declare symbols inside of a .h file or a .cpp file. We often implement those symbols (mostly operations) in .cpp files. It is also not uncommon to find complete "implementations" in .h files, particularly in the world of STL.
However, let's discuss the need for specifying the symbol in terms of declaring it and the separate issue of actually locating it and linking it in during the linker's execution. For compilation (and often even during pre-processing) we need to have the definition of the symbol available to the tool (and the files being worked on by the tool) so that it can "check" things to ensure that we're not violating any of the many rules that it requires for a valid program implementation to exist.
Note that in the following code:
Code:
class Foo
{
public:
Foo();
Foo( int x );
private:
int m_value;
};
...that we may locate this in a .h file or a .cpp file, since this is a simple definition of a few symbols. If we placed this "declaration" in a .cpp file and not a .h file, it would be harder to share the definition of Foo with any other pieces of code that may also want to use or interact with a Foo instance. So, if we placed this code in a .h file (along with a multiple inclusion guard), we would then be able to #include <Foo.h> anywhere that we needed to use a Foo class. In other words, the .h "exports" the definitions of the symbols, while the .cpp file imports them (using the #include pre-processor directive) and, in-turn, (often) implements those symbols so that they will be compiled into object files used by the linker.
The header file doesn't need to #include the .cpp file, since the header is merely telling us that these symbols are being declared as being present in some compilation unit, but they (often) are not implemented in the .h file, as shown in the previous Foo.h example. In a way, it is like a recipe for something that you would cook. It tells us that we need the "ingredients" that go into making the food, but it is not the ingredients or the "food" itself, which occurrs in the .cpp file. And, like the recipe analogy, where the recipe will give you directions of how you should go about implementing the food item, in C++ we can specify "behavoiral specifications" that tell classes that derive from a base class that they must implement the required operations in order to be a part of the system. In other words, the notion of "pre-heating the oven to 350*" can be made a requirement in our .h files so that any derived class must ensure that the functionality is implemented.
Some materials show #include-ing .cpp files, though it tends to be a practice that is frowned upon by most professional programmers.
:davis: