views:

155

answers:

5

I'm fairly new to C++, but my understanding is that a #include statement will essentially just dump the contents of the #included file into the location of that statement. This means that if I have a number of '#include' and 'using' statements in my header file, my implementation file can just #include the header file, and the compiler won't mind if I don't repeat the other statements.

What about people though?

My main concern is that if I don't repeat the '#include', 'using', and also 'typedef' (now that I think of it) statements, it takes that information away from the file in which it's used, which could lead to confusion.

I am just working on small projects at the moment where it won't really cause any issues, but I can imagine that in larger projects with more people working on them it could become a significant issue.

An example follows:

UPDATE: my function prototypes for 'Unit' have string, ostream and StringSet among their return types and parameters - I am not including anything in my header file that is used only in the implementation file.

//Unit.h

#include <string>
#include <ostream>
#include "StringSet.h"

using std::string;
using std::ostream;

class Unit {

public:
    //public members with string, ostream and StringSet
    //in their return values/parameter lists
private:
    //private members
    //unrelated side-question: should private members
    //even be included in the header file?
} ;


//Unit.cpp

#include "Unit.h"

//The following are all redundant from a compiler perspective:
#include <string>
#include <ostream>
#include "StringSet.h"

using std::string;
using std::ostream;

//implementation goes here
+4  A: 

You should never have a using statement in a header unless it it contained within a function. It is bad practice. What if somebody else included a line like using mylib::string in their header file? Then you've got problems.

As far as typedef goes...it isn't just a shortcut, it has semantic meaning. typedef defines a type, so you really should never redeclare it. For example, this is an error:

typedef int   myint;
typedef float myint;

because of conflicting types.

For repeating #include, you should consider if you actually need to include the file in the header in the first place. Perhaps a forward declaration fits your needs.

Travis Gockel
I have updated the question to clarify: I avoid having any #includes in my header file unless I actually need them in the header file. I'm not sure if that forward declaration example applies if I'm making use of std::string or another class that I'm not defining - can you clarify how this would work if so?
Dr. Monkey
The problem with `std::string` is that it is really just `typedef basic_string<char> string` ... the standard states: `It is undefined for a C++ program to add declarations or definitions to namespace std or namespaces within namespace std unless otherwise specified.` So...you can't forward-declare it. As far as the `really_long_namespace_name` question, this is where people use member types. `std::allocator` is a good example of this: http://www.cplusplus.com/reference/std/memory/allocator/
Travis Gockel
A: 

Keep the header files to a minimum. This means as little include's as feasible. the .cpp file will usually include the corresponding header as well as any other headers necessary for implementation.

Nick
A: 

Like Travis said, you shouldn't have using statements in a header file because that means they will be included in all the translation units that include that header file, which can cause confusing issues.

If I only require the functionality from a header file in a cpp file, I only include it in that cpp file. It's good practice for larger projects because it means less work for the compiler. Also, wherever possible, I use forward declarations in the headers instead of includes (and again, include the headers in the cpp file).

Alex - Aotea Studios
A: 

It's considered bad form to have a using statement in a header file at all, unless you are intentionally duplicating a symbol into a different namespace. It's ok to use in a cpp file.

Each typedef should exist only once in your codebase. That should be in a header file if it needs to be used in multiple cpp/h files. Duplicating them will cause you much grief.

A header file should have all the #include statements that it needs, and no others. If only pointers to a class are mentioned then use a forward declaration rather than including the header. Any other includes that are required only inside the cpp file should go there. Repeating the includes from the header is ok, but not required. It's just a style choice.

Alan
A: 
  • Only include in a header/source what you really need (if forward declarations are available, and enough, then forward declare instead of including)
  • Don't use using statement in headers (unless inside function scopes)... Adding using in the header will pollute the namespaces of all the sources including the header.
  • You should make sure each file (header of source) includes everything it needs, and nothing more.

You don't need to care if some includes are redundant. Header guards and precompiler optimizations are there to handle that for you.

You should be able to manipulate each file in isolation.

For example, let's say you use the std::string in the header and in the source, but, as an "optimization", you only included the string in the header... If you discover later you don't need anymore the string in the header, and want to remove it (code cleaning, and all...), you will have to modify the source to include the string. Now, let's imagine you have TEN sources including the header...

Now, of course, you can have exceptions to this rule (for example, precompiled headers, or even headers woe sole aim is to do multiple includes as a courtesy), but by default, you should have self-sufficient header and source files (i.e. files that include anything they use, no more no less).

paercebal