in depth explaination...

J

josh

hi all,
If I have an interfacce file i.e. Time.h (where inside it I've #ifndef/
#define / #endif directives) and then an implementation file i.e.
Time.cpp in which I include Time.h and then a client file i.e. Test.cpp
in which I include again Time.h I undtestand that the directives
#ifndef/ #define / #endif make to insert one time only the file but
I must anyway to include Test.h in Test.cpp for using the class I
defined in Time.h else the compiler can't resolve the name......

so I'm very confused..please help me
 
S

Scott McPhillips [MVP]

josh said:
hi all,
If I have an interfacce file i.e. Time.h (where inside it I've #ifndef/
#define / #endif directives) and then an implementation file i.e.
Time.cpp in which I include Time.h and then a client file i.e. Test.cpp
in which I include again Time.h I undtestand that the directives
#ifndef/ #define / #endif make to insert one time only the file but
I must anyway to include Test.h in Test.cpp for using the class I
defined in Time.h else the compiler can't resolve the name......

so I'm very confused..please help me

#ifndef/ #define / #endif is called an "include guard."

It's purpose is NOT to insert the file one time only.

It's purpose is to insert the file one time only WHILE compiling
time.cpp, and to insert the file one time only WHILE compiling test.cpp.
In other words, it prevents recursively including the same h file twice
within one cpp file.

Each cpp file is compiled separately and is compiled independently of
all other cpp files.
 
J

josh

It's purpose is NOT to insert the file one time only.

It's purpose is to insert the file one time only WHILE compiling
time.cpp, and to insert the file one time only WHILE compiling test.cpp.
In other words, it prevents recursively including the same h file twice
within one cpp file.

Each cpp file is compiled separately and is compiled independently of
all other cpp files.

so it prevents doing this:

if I have a file named Date.h in which I have...
#include "Time.h"
....

and then in Test.cpp I make

#include "Date.h"
#include "Time.h"

here Time.h is not included ... right?
 
E

eriwik

if I have a file named Date.h in which I have...
#include "Time.h"
...

and then in Test.cpp I make

#include "Date.h"
#include "Time.h"

here Time.h is not included ... right?

Only once, from the include in Date.h
 
B

blangela

josh said:
so it prevents doing this:

if I have a file named Date.h in which I have...
#include "Time.h"
...

and then in Test.cpp I make

#include "Date.h"
#include "Time.h"

here Time.h is not included ... right?

Very good! You picked that up very fast. In fact, the example code you
provided above is a much more "real life" example of where the #ifndef
etc. is required. If it is used to prevent a recursive type situation,
as described in an earlier post, my take on it is that the programmer
has made a logic error. The situation you describe above is more of an
oversight than a actual error in logic. At least, that is my take on
it.

Bob L.
 
J

josh

provided above is a much more "real life" example of where the #ifndef
etc. is required. If it is used to prevent a recursive type situation,
as described in an earlier post, my take on it is that the programmer
has made a logic error. The situation you describe above is more of an
oversight than a actual error in logic. At least, that is my take on
it.

Bob L.

yes I agree with you and then I wonder me if I have the situation as
described above
there is no sense that the compiler includes more times the file
(Time.h) with
separate units (i.e. Test1.cpp Test2.cpp etc). Why the preprocessor and
then the linker doesn't take all
the files and then check if defined an include unit and so it includes
**really** one
time only???
 
B

blangela

josh said:
yes I agree with you and then I wonder me if I have the situation as
described above
there is no sense that the compiler includes more times the file
(Time.h) with
separate units (i.e. Test1.cpp Test2.cpp etc). Why the preprocessor and
then the linker doesn't take all
the files and then check if defined an include unit and so it includes
**really** one
time only???

The linker simply links the separately compiled .cpp files. It is very
important to realize that .h files are_NOT_ compiled as separate units.
The C++ code in a .h file is only compiled if it is included in a .cpp
file.

Let us say that you have 3 .cpp files in your project. Each of these
files are compiled separately. In fact it is very common to compile
each .cpp file as required, and _not_ all at the same time.

When you request to compile a .cpp file, the preprocessor executes
first. One of the commands that it executes is the #include statement.
The best way to think of the #include is as a copy and paste -- it
copies the included file on top of (replacing IOW) the #include
statement. If you have made a logic error of some type (as described
in earlier posts) and do not have a safety system in place (like the
#ifndef ...) then your compile will go off the rails because of an
endless loop or because you compile the same .h file more than once.
After the preprocessor is done, the actual compile of the (now
modofied) .cpp file begins.

Beginning C++ programmers have difficult time with this concept. For
example if you leave off the ending ';' (semicolon) of your class
definition in the class interface file (the .h file IOW), the error
message (for some compilers) will appear near the beginning of the .cpp
file that includes it. So then the student comes to me in a panic
(typically in a lab exam) stating that they can see absolutely nothing
wrong with their ctor, they have forgotten that the .h file included
before the implementation of their ctor was compiled before the ctor,
and that is where the error is originating from.

I hope that clears up your question.

Bob L.
 
B

BobR

blangela wrote in message ...
The linker simply links the separately compiled .cpp files. It is very
important to realize that .h files are_NOT_ compiled as separate units.
The C++ code in a .h file is only compiled if it is included in a .cpp
file.
Let us say that you have 3 .cpp files in your project. Each of these
files are compiled separately. In fact it is very common to compile
each .cpp file as required, and _not_ all at the same time.

When you request to compile a .cpp file, the preprocessor executes
first. One of the commands that it executes is the #include statement.
The best way to think of the #include is as a copy and paste -- it
copies the included file on top of (replacing IOW) the #include
statement.

To push that point:

Most people think that they have to put the #include at the top of a (*.cpp,
*.h) file. Fact is, they can be (almost) anywhere the included code is valid.

Make two files:

// --- Guts.h ---
std::cout<<"Hello World, from Guts.h"<<std::endl;
#define BLAHBLAH std::cout<<"Hello World2, from Guts.h"<<std::endl;
// --- be sure that is all on one line! ---
// --- Guts.h --- END

// --- GutsMain.cpp ---
#include <iostream>
#include <ostream>

int main(){
#include "Guts.h"
BLAHBLAH
// looks weird, eh. (no semicolon at end)
// note that very tricky nameing.<G>
return 0;
}
// --- GutsMain.cpp --- END

Compile 'GutsMain.cpp' and run it.

Of course, using something like that in a real program would be insane [1].
It's just to point out how '#include' and '#define' work.

[1] - note that "Guts.h" depended on the std headers included in the
"GutsMain.cpp". That should be avoided. Always include headers where needed,
and let the 'include guards' do their job.
 
B

blangela

BobR said:
blangela wrote in message ...
The linker simply links the separately compiled .cpp files. It is very
important to realize that .h files are_NOT_ compiled as separate units.
The C++ code in a .h file is only compiled if it is included in a .cpp
file.
Let us say that you have 3 .cpp files in your project. Each of these
files are compiled separately. In fact it is very common to compile
each .cpp file as required, and _not_ all at the same time.

When you request to compile a .cpp file, the preprocessor executes
first. One of the commands that it executes is the #include statement.
The best way to think of the #include is as a copy and paste -- it
copies the included file on top of (replacing IOW) the #include
statement.

To push that point:

Most people think that they have to put the #include at the top of a (*.cpp,
*.h) file. Fact is, they can be (almost) anywhere the included code is valid.

Make two files:

// --- Guts.h ---
std::cout<<"Hello World, from Guts.h"<<std::endl;
#define BLAHBLAH std::cout<<"Hello World2, from Guts.h"<<std::endl;
// --- be sure that is all on one line! ---
// --- Guts.h --- END

// --- GutsMain.cpp ---
#include <iostream>
#include <ostream>

int main(){
#include "Guts.h"
BLAHBLAH
// looks weird, eh. (no semicolon at end)
// note that very tricky nameing.<G>
return 0;
}
// --- GutsMain.cpp --- END

Compile 'GutsMain.cpp' and run it.

Of course, using something like that in a real program would be insane [1].
It's just to point out how '#include' and '#define' work.

[1] - note that "Guts.h" depended on the std headers included in the
"GutsMain.cpp". That should be avoided. Always include headers where needed,
and let the 'include guards' do their job.

An example of puttng an #include statement at the end of a file is for
a template class. Some programmers will have an #include statement at
the end of the template class interface file, to effectively append the
implementation of the template member functions of the class to the end
of the class interface. This allows for still having separate files
for both the template class interface and the template class
implementation, as per usual.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top