What sense do h files make in c/cpp?

X

xz

What sense do h files make in c/cpp?


I never thought about this question before.

Does the existence of h files make sense at all?

Why do we need to declare functions in h files and define/implement
them in cpp?
 
M

Mark P

xz said:
What sense do h files make in c/cpp?


I never thought about this question before.

Does the existence of h files make sense at all?

Why do we need to declare functions in h files and define/implement
them in cpp?

When you write code you can either: 1) put everything into a single file
or, 2) separate your code into multiple files. Except for very small
projects, option 1 is not practical, possible, and/or desirable. One
enormous source file is difficult to maintain (not to mention,
comprehend), slow to compile, and often outright impossible, such as
when interfacing with third party code for which the source is not
publicly available.

C++ supports "separate compilation" which means that individual source
files can be compiled separately and the end result can be combined into
an executable. Invariably parts of one source file will make reference
to parts of another source file (e.g., calling a function or using a
class defined elsewhere). The header file typically contains the
minimum information necessary for the compiler to understand such a
reference to the contents of another source file.

-Mark
 
X

xz

Thank you for your reply.

But I was not asking about Single File vs Multiple Files.
I definitely understand the significance of separating code into
different files.

However, why don't we always put the code describing one object, i.e.
both the declaration and the definition of one class, in the same
file, say, the cpp file?
When using this class, you can simply include the corresponding cpp
file, instead of include the h file like what we are currently doing.

If the use of h file is only for the speed of compiling, I don't see
much significance.
It's not worth to make the structure of the files much more
complicated only to save a little compiling time.
 
X

xz

Here is am example for what I am talking about:

Declare and define the Apple class in one single file "Apple.cpp".
Then include this file in the "AppleTest.cpp" file to use it.

//Apple.cpp
#include<iostream>

using namespace std;

class Apple{
public:
void print();
};

void Apple::print() {
cout<<"I am an apple"<<endl;
}

//AppleTest.cpp
#include "Apple.cpp"

using namespace std;

int main() {
Apple apple;
apple.print();
}
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

Thank you for your reply.

First off, please don't top-post, and don't quote signatures, thanks.
But I was not asking about Single File vs Multiple Files. I
definitely understand the significance of separating code into
different files.
>
However, why don't we always put the code describing one object, i.e.
both the declaration and the definition of one class, in the same
file, say, the cpp file?
When using this class, you can simply include the corresponding cpp
file, instead of include the h file like what we are currently
doing.

Because if you do it that way you'll have to compile that code each time
you include it in some other file. By separating it you only have to
compile it once. Imagine a large project with a .h/.cpp pair of files
describing a class using throughout the project, imagine that this class
is quite big, and that the project have a couple of hundred files. With
your solution you'd have to compile that large class a couple of hundred
times, as it is now you only have to do it once.
If the use of h file is only for the speed of compiling, I don't see
much significance.
It's not worth to make the structure of the files much more
complicated only to save a little compiling time.

For large projects it not just a little time, it might be quite
significant amounts of time. Remember that the most expensive thing in
software development is the people working on the project, each minute
they have to wait on the compiler is wasted money.
 
M

Mark P

xz said:
Here is am example for what I am talking about:

Declare and define the Apple class in one single file "Apple.cpp".
Then include this file in the "AppleTest.cpp" file to use it.

//Apple.cpp
#include<iostream>

using namespace std;

class Apple{
public:
void print();
};

void Apple::print() {
cout<<"I am an apple"<<endl;
}

//AppleTest.cpp
#include "Apple.cpp"

using namespace std;

int main() {
Apple apple;
apple.print();
}

Please don't top-post. Reply below or interleaved with previous posts.

There are a few problems with doing what you suggest. First, as I
mentioned in my earlier reply, you don't always have access to all of
the source code. If you need to link against a third party library, the
header files may be all you get. Likewise, you may want to release a
library as a compiled object and others will need the header file to
access your work.

Another of the advantages of separate compilation is that, if you change
one source file, you generally don't have to recompile all of the other
source files in your project. If you've ever worked on a large software
project you'll know that a complete compile can take hours to complete.
That would be downright unbearable in a development environment.

A separate issue is that this sort of structure can become an
organizational nightmare. Your example is very simple, but what happens
when you have to assemble 100 or 1000 such files together into one big
file? The one-definition rule (ODR) of C++ means you have to be very
careful when you #include source files not to duplicate anything. And
if you include each file exactly once you have to make sure that they're
ordered properly so that you never refer to an undeclared entity. This
is essentially a topological sort of the dependencies between source
files which you must maintain at all times. The appeal of header files
is that each source file can #include exactly what it needs without
worrying about sequencing or redundancy and the linker will sort it all
out in the end, resolving duplicate declarations and linking in external
entities wherever they may reside in other source files.

-Mark
 
J

James Kanze

But I was not asking about Single File vs Multiple Files.
I definitely understand the significance of separating code into
different files.
However, why don't we always put the code describing one object, i.e.
both the declaration and the definition of one class, in the same
file, say, the cpp file?

Because that's a bad policy. The two are generally the
responsibility of two different people. It's important to keep
them separate, and since files seem to be the organisational
method of choice...
When using this class, you can simply include the corresponding cpp
file, instead of include the h file like what we are currently doing.

Again, files seem to be the organisational method of choice:).
In this case, the choice has been made by the build
system---all of the build systems I know are file based.
Including a .cpp file will mean recompiling all of the client
code any time you make a minor change in the implementation.
Definitly to be avoided.

And again, it would mean that you cannot acquire modification
rights on the implementation without also acquiring them on the
interface. Which is not a good thing.
If the use of h file is only for the speed of compiling, I don't see
much significance.

You don't see much significance between having to recompiler 20
or 30 lines, and having to recompile 2 million lines, just
because of trivial change in the implementation?
It's not worth to make the structure of the files much more
complicated only to save a little compiling time.

First, I think that the "complexity" is necessary for other
reasons anyway. But I don't consider a difference between 5 or
10 seconds and several hours just "a little".
 
T

Taran

Because that's a bad policy. The two are generally the
responsibility of two different people. It's important to keep
them separate, and since files seem to be the organisational
method of choice...


Again, files seem to be the organisational method of choice:).
In this case, the choice has been made by the build
system---all of the build systems I know are file based.
Including a .cpp file will mean recompiling all of the client
code any time you make a minor change in the implementation.
Definitly to be avoided.

And again, it would mean that you cannot acquire modification
rights on the implementation without also acquiring them on the
interface. Which is not a good thing.


You don't see much significance between having to recompiler 20
or 30 lines, and having to recompile 2 million lines, just
because of trivial change in the implementation?


First, I think that the "complexity" is necessary for other
reasons anyway. But I don't consider a difference between 5 or
10 seconds and several hours just "a little".

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

And also all the function definitions which are in the .cpp file are
compiled and put in their respective .o (object files). So if you
include the .cpp files the function definitions are then compiled
again with the .cpp which includes this .cpp file and then the linker
will say " there are multiple definitions of the same function" in
file_included.o and file_which_includes.o
The linker may either complain and stop or it may link with the first
symbol it found, which incidently is correct in this case and doesn't
absolve you of the sin.

Hope That Helps.
 
J

Juha Nieminen

xz said:
What sense do h files make in c/cpp?

1) You often want to create functions, types and constants which
are local to one compilation unit and which you don't want
interfering with the rest of the program. For example, you might
want to have something like this in a cpp file:

namespace { const int LOOPS = 42; }

and you want that to be local to the current cpp file and not seen
anywhere else. You don't need to worry if some other cpp also uses
the name "LOOPS" for something completely different.

2) Related to 1, but more generally: By exposing the entire cpp file
to other cpp files, you are breaking the principle of minimal public
interfaces. A header file should contain as little code as possible:
That is, the public interface of that module and the bare minimum
implementation details enforced by technical reasons of the compiler.
All the implementation details which are not necessary in the header
file for technical reasons should be "hidden" in the cpp file. This
increases abstraction and modularity, which is good in the long run.

3) For technical reasons, if you are going to include a cpp file in
more than one other cpp file, all the functions in that cpp file must
be 'inline' or else you will get linker errors because of duplicate
implementations.

4) Related to that: If you have a static member variable or a static
variable local to that cpp file (usually inside a nameless namespace
or such), you *will* get a linker error if you include the cpp file in
more than one other cpp file. That's because the linker will see two
instances of that static variable and has no way of knowing which one
it should use. You can't "inline" static variables as you can do with
functions.

5) Compiling each cpp file separately (and keeping all headers as
minimal as possible and with as few #includes as possible) will
greatly speed compilation times in large projects. Usually if you
just modify one cpp file then the compiler just has to recompile
that cpp file and then it can link everything into the final binary.
If, however, that cpp file was included in dozens of other cpp files,
which in turn are included in dozens of others and so on, modifying
one cpp file may suddenly require for the compiler to recompile most
of the others too, for no good reason. With very large projects that
could take hours instead of a few seconds.

6) Likewise, compiling one cpp file would take much longer if it
includes dozens of other cpp files (which themselves include dozens
of others and so on).

7) If module A references module B, and module B references module A,
you have a problem. With minimal headers this problem can usually
be solved (as long at least one of A or B uses only references/pointers
to the other). However, if you always included the cpp files, you would
have no solution to this problem.

8) Header/source file pairs is not the only possible way of compiling.
Bunch-of-headers/big-precompiled-library is another very common
situation (which is actually almost always the case with the standard
libraries of the compiler). There's no reason why you would want to
have the entire source code of the library when just the headers are
enough to use it.
 
X

xz

Sorry for top-posting and thanks for reminding. I am a rookie here
that I did not know much about those things.

Also, thank you guys a lot for providing so many details.

I am actually switching from Java to C++. And in Java, I don't have
this header file thing. That's why I had the question.

Now, my understanding is that h files work as an interface between the
developers of the modules (the corresponding cpp files or the .o
files) and the users of the modules, i.e. the clients.
So they are like manuals and control panels. Basically, you read the h
files to know the usage of the classes and functions, and use them by
dealing with the h files.
Is that correct?
 
O

Owen Jacobson

Sorry for top-posting and thanks for reminding. I am a rookie here
that I did not know much about those things.

Also, thank you guys a lot for providing so many details.

I am actually switching from Java to C++. And in Java, I don't have
this header file thing. That's why I had the question.

Now, my understanding is that h files work as an interface between the
developers of the modules (the corresponding cpp files or the .o
files) and the users of the modules, i.e. the clients.
So they are like manuals and control panels. Basically, you read the h
files to know the usage of the classes and functions, and use them by
dealing with the h files.
Is that correct?

Java .class files carry much more metadata than compiled C++ does
which can be used to reconstruct the "header" for the Java class
contained in it. C++ does not dictate a binary format at all; most C+
+ compilers only include metadata in the resulting binary about the
classes and functions when told to include debugging symbols.

Header files do function as documentation, as you describe, but they
also function as a source of function and object prototypes for the
compiler, so that it knows what symbols are defined and what symbols
aren't. In java, when compiling a class Client that uses another
class Provider, the file Provider.class must be available (or its
source) so that javac can resolve symbols; in C++ the header file
performs that role.
 
J

James Kanze

xz said:
I am actually switching from Java to C++. And in Java, I don't have
this header file thing.

That is, of course, a major defect of Java. Not that it doesn't
have header files, per se, of course---the C++ solution of
textual inclusion is far from elegant---but that it doesn't have
any means whatsoever of separating the external specification
from the actual code. That makes Java significantly more
difficult to use in larger projects.
That's why I had the question.
Now, my understanding is that h files work as an interface between the
developers of the modules (the corresponding cpp files or the .o
files) and the users of the modules, i.e. the clients.
So they are like manuals and control panels. Basically, you read the h
files to know the usage of the classes and functions, and use them by
dealing with the h files.
Is that correct?

More or less. I'm not sure about "reading the .h files"; on
most of the larger projects I've been on, they've been
automatically generated from the specifications (using Rational
Rose, or something of that sort), and aren't necessarily very
readable. But the .h files do represent a different type of
information, generally created at a different level. (This
isn't totally true, since they have to specify the private
members of the class as well. But with rigorous use of the
compilation firewall idiom...)
 

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,770
Messages
2,569,586
Members
45,084
Latest member
HansGeorgi

Latest Threads

Top