including files best practice

O

ouroboros84

Please find here below a simple example. I know that a .hpp file has to include or forward declare everything it uses I wonder if it is best practice to include all .hpp files that are used in the .cpp file as well. I am asking this because I recently saw on a new project I am working on, that people tend to avoid including headers in a lot of cpp files.

In this case: is it good to include b.hpp in a.cpp? I know it has already been included by including a.hpp, but I personally feel that if a symbol appears in a .cpp, it should be included (or forward declared if possible)

a.hpp

#pragma once
#include "b.hpp"

class C; //forward declaration of C

class A
{
public:
B get_b();
private:
B _b;
C* _c;
};

a.cpp

#include "a.hpp"
//needed or I can leave it out, since B is included already in a.hpp?
#include "b.hpp"

B A::get_b()
{
return _b;
}
 
J

Jorgen Grahn

Please find here below a simple example. I know that a .hpp file has
to include or forward declare everything it uses

It doesn't /have to/ -- although it can be rather confusing if a file
which just says #include "foo.hpp" doesn't compile.
I wonder if it is
best practice to include all .hpp files that are used in the .cpp file
as well. I am asking this because I recently saw on a new project I am
working on, that people tend to avoid including headers in a lot of
cpp files.

No, that's not best practice.
In this case: is it good to include b.hpp in a.cpp? I know it has
already been included by including a.hpp, but I personally feel that
if a symbol appears in a .cpp, it should be included (or forward
declared if possible)

My personal rule is this: if I have a pair foo.cpp/foo.hpp, I always
do a

#include "foo.hpp"

first in that cpp file. That's an automatic check that foo.hpp is
idempotent. Then you can do almost whatever you want and not end up
with a nasty effects like "I included foo.hpp from a new source file,
and had to spend half an hour finding out which other files I needed
to pull in first".

I try not to have a foo.hpp pull in a /lot/ of other headers which it
doesn't really need, but it's not a big disaster if it it pulls in a
few too many.

/Jorgen
 
V

Victor Bazarov

Please find here below a simple example. I know that a .hpp file has
to include or forward declare everything it uses I wonder if it is best
practice to include all .hpp files that are used in the .cpp file as
well. I am asking this because I recently saw on a new project I am
working on, that people tend to avoid including headers in a lot of cpp
files.
In this case: is it good to include b.hpp in a.cpp? I know it has
already been included by including a.hpp, but I personally feel that if
a symbol appears in a .cpp, it should be included (or forward declared
if possible)
a.hpp

#pragma once
#include "b.hpp"

class C; //forward declaration of C

class A
{
public:
B get_b();
private:
B _b;
C* _c;
};

a.cpp

#include "a.hpp"
//needed or I can leave it out, since B is included already in a.hpp?
#include "b.hpp"

B A::get_b()
{
return _b;
}

I second this.

I would include it since 'B' type is used in a.cpp. Cannot (and should
not) rely on 'b.hpp' being pulled in by 'a.hpp'.

Of course, it's a style question, not a necessity. If it's pulled in
twice, it should contain the double inclusion guards, etc. And if it's
not included after somebody edits 'a.hpp' file, an attempt to compile
'a.cpp' will reveal that. But I still include all those things, myself.

V
 
O

ouroboros84

Il giorno giovedì 14 novembre 2013 23:14:02 UTC+1, Jorgen Grahn ha scritto:
No, that's not best practice.

Imagine though, if now in a.cpp you had this, as you suggest:

#include "a.hpp"
//#include "b.hpp" deleted

B A::get_b()
{
return _b;
}

namespace {
B b; //I can instanciate it
// even if I don't have the header
//thanks to an im[licit inclusion from a.hpp
C = b.get_c() //I can do it as well because a.hpp -> b.hpp -> c.hpp
}


wouldn't that cause problems? imagine if someone deleted c.hpp inclusion from b.hpp, using a forward declare for returning a reference instead of a value.
in that case a.cpp wouldn't compile anymore.

I prefer to be explicit in what I have to include in every class.
for example it is rare that you need to include a <string> header, but you basically do it every time you use a string.
 
O

ouroboros84

Il giorno giovedì 14 novembre 2013 23:27:48 UTC+1, Victor Bazarov ha scritto:
to include or forward declare everything it uses I wonder if it is best

practice to include all .hpp files that are used in the .cpp file as

well. I am asking this because I recently saw on a new project I am

working on, that people tend to avoid including headers in a lot of cpp

files.



already been included by including a.hpp, but I personally feel that if

a symbol appears in a .cpp, it should be included (or forward declared

if possible)








I second this.



I would include it since 'B' type is used in a.cpp. Cannot (and should

not) rely on 'b.hpp' being pulled in by 'a.hpp'.



Of course, it's a style question, not a necessity. If it's pulled in

twice, it should contain the double inclusion guards, etc. And if it's

not included after somebody edits 'a.hpp' file, an attempt to compile

'a.cpp' will reveal that. But I still include all those things, myself.



V


thanks, I prefer to include them myself too. I was just wondering if there was a common agreement in the C++ commmunity, but as usual it seems there isn't one :)
 
J

Jorgen Grahn

Il giorno giovedì 14 novembre 2013 23:14:02 UTC+1, Jorgen Grahn ha scritto:

Imagine though, if now in a.cpp you had this, as you suggest:

I'm not sure I suggested that. However ...
#include "a.hpp"
//#include "b.hpp" deleted

B A::get_b()
{
return _b;
}

namespace {
B b; //I can instanciate it
// even if I don't have the header
//thanks to an im[licit inclusion from a.hpp
C = b.get_c() //I can do it as well because a.hpp -> b.hpp -> c.hpp
}
wouldn't that cause problems? imagine if someone deleted c.hpp
inclusion from b.hpp, using a forward declare for returning a
reference instead of a value. in that case a.cpp wouldn't compile
anymore.

I have a hard time following your examples; I can't remember a c.hpp
in your first posting.

But anyway: ok, so someone removes an #include from some header file,
because it's not strictly needed there. And building something else
fails.

For me that's perfectly fine. I have all the sources; I can rearrange
them as needed. I myself was probably that someone who made the
change, a few seconds earlier -- because noone would change a header
file and commit without checking if it at least built!

I guess this means I'm assuming you're not developing isolated
components or libraries. Things are different and a lot harder if you
do. But (a) very few people need to do that, and (b) there are
several other worries you have in that case.

It /is/ a real problem for library writers and users though: many
times I've upgraded my compiler or standard library and had code stop
building, because #include <iostream> no longer pulls in <ostream>, or
something. I see no way around this.

/Jorgen
 
A

Alf P. Steinbach

On 14.11.2013 22:34, ouroboros84 wrote:
[snip]
a.cpp

#include "a.hpp"
//needed or I can leave it out, since B is included already in a.hpp?
#include "b.hpp"

B A::get_b()
{
return _b;
}

In this case the full class B definition is not needed for class A's
public interface. So there is a possibility that class A will be changed
so that [b.hpp] is not needed for [a.hpp]. However, changing [a.hpp]
will usually be accompanied by a corresponding change of [a.cpp], so
there's problem with THIS file, whatever you decide.

The main problem is with client code. A programmer using [a.hpp] cannot
know whether [b.hpp] is guaranteed made available or is just present as
an implementation aspect that might be changed at any time. That's
because the complete class B definition is not needed for A's /public/
interface, only for its implementation, and so some optimization of
class A (e.g. for build time) might result in [b.hpp]'s removal.

So if I was concerned about this kind of problem then I would document
in some way whether [b.hpp] is present by design or as just an
implementation aspect.


* * *

In some cases you absolutely know that a header will be made available
by some other header. For example, a header that exposes something that
involves Windows API things will, as a rule, guaranteed include
<windows.h>. But that does not mean that client code can avoid including
<windows.h>. On the contrary, that Microsoft header, the "mother of all
headers", provides a set of declarations that depends strongly on
various macro symbols, plus that a great many of the declarations
themselves depend on various macro symbols. Thus to ensure consistent
declarations and a consistent set of declarations, it is a good idea to
include this header before including headers that depend on it. Other
3rd party headers may be similarly badly designed.

* * *

To ensure that headers are free-standing (that they're "idempotent")
it's a good idea to include each header at the top in /some/ [.cpp]
file. For header only modules I use a dummy [.cpp] file. E.g.,
[blahblah.h] is included by [blahblah.h.dummy.cpp], if it isn't included
by a real implementation file [blahblah.cpp].

With some toolsets (in particular Microsoft's) this necessitates turning
off librarian warnings about unused stuff.

Also note that this practice ties in with the previous section, ensuring
that those headers that need some H do include it.

* * *

Microsoft's precompiled header feature, which is on by default in a
Visual Studio project, can make incorrect code compile and can cause
errors with correct code. It's no big deal to adjust the code but it
means that code compiled with this feature may not necessarily work with
some other compiler. I do not know of any good solution.


Cheers & hth.,

- Alf
 
T

Tobias Müller

Alf P. Steinbach said:
Microsoft's precompiled header feature, which is on by default in a
Visual Studio project, can make incorrect code compile and can cause
errors with correct code. It's no big deal to adjust the code but it
means that code compiled with this feature may not necessarily work with
some other compiler. I do not know of any good solution.

I know you are not reading my posts but maybe someone else can explain
that.
I always use precompiled headers and never had problems with them.
Given that they are set up correctly of course.

Tobi
 
A

Alf P. Steinbach

september.org:


There is a bug in MSVC that any code before #include "precompiled.h" line
is ignored. For ignored #include lines they issue a warning, but other code
is ignored silently. I guess this is what Alf meant.

Yep.

Thanks,

- Alf
 
J

James Kanze

I second this.
I would include it since 'B' type is used in a.cpp. Cannot (and should
not) rely on 'b.hpp' being pulled in by 'a.hpp'.

In general, I would agree. But one can consider this a special
case; if the definition of A requires a full definition of B,
then A must have included b.hpp, and of course, in a.cpp, you
know this, because you are implementing the private parts of A.
So it doesn't seem as essential to me as it normally would be.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top