You should definitely NOT use using namespace in headers for precisely the reason you say, that it can unexpectedly change the meaning of code in any other files that include that header. There's no way to undo a using namespace which is another reason it's so dangerous.
Code in header files should always use the fully qualified namespace name. The following example shows a namespace declaration and three ways that code outside the namespace can accesses their members.
If a header file happens to be included twice, the compiler will process its contents twice. This is very likely to cause an error, e.g. when the compiler sees the same structure definition twice. Even if it does not, it will certainly waste time. This construct is commonly known as a wrapper #ifndef.
Since you can't put a namespace using statement at the top level of the header file, you must use a fully qualified name for Standard Library classes or objects in the header file. Thus, expect to see and write lots of std::string, std::cout, std::ostream, etc. in header files.
You should definitely NOT use using namespace
in headers for precisely the reason you say, that it can unexpectedly change the meaning of code in any other files that include that header. There's no way to undo a using namespace
which is another reason it's so dangerous. I typically just use grep
or the like to make sure that using namespace
isn't being called out in headers rather than trying anything more complicated. Probably static code checkers flag this too.
The header should include just the headers that it needs to compile. An easy way to enforce this is to always include each source file's own header as the first thing, before any other headers. Then the source file will fail to compile if the header isn't self-contained. In some cases, for example referring to implementation-detail classes within a library, you can use forward declarations instead of #include
because you have full control over the definition of such forward declared class.
I'm not sure I would call it common, but it definitely shows up once in a while, usually written by new programmers that aren't aware of the negative consequences. Typically just a little education about the risks takes care of any issues since it's relatively simple to fix.
Item 59 in Sutter and Alexandrescu's "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices":
59. Don’t write namespace usings in a header file or before an #include.
Namespace
using
s are for your convenience, not for you to inflict on others: Never write ausing
declaration or ausing
directive before an#include
directive.Corollary: In header files, don't write namespace-level
using
directives orusing
declarations; instead, explicitly namespace-qualify all names.
A header file is a guest in one or more source files. A header file that includes using
directives and declarations brings its rowdy buddies over too.
A using
declaration brings in one buddy. A using
directive brings in all the buddies in the namespace. Your teachers' use of using namespace std;
is a using directive.
More seriously, we have namespaces to avoid name clash. A header file is intended to provide an interface. Most headers are agnostic of what code may include them, now or in the future. Adding using
statements for internal convenience within the header foists those convenient names on all the potential clients of that header. That can lead to name clash. And it's just plain rude.
You need to be careful when including headers inside of headers. In large projects, it can create a very tangled dependency chain that triggers larger/longer rebuilds than were actually necessary. Check out this article and its follow-up to learn more about the importance of good physical structure in C++ projects.
You should only include headers inside a header when absolutely needed (whenever the full definition of a class is needed), and use forward declaration wherever you can (when the class is required is a pointer or a reference).
As for namespaces, I tend to use the explicit namespace scoping in my header files, and only put a using namespace
in my cpp files.
Check out the Goddard Space Flight Center coding standards (for C and C++). That turns out to be a bit harder than it used to be - see the updated answers to the SO questions:
The GSFC C++ coding standard says:
§3.3.7 Each header file shall
#include
the files it needs to compile, rather than forcing users to#include
the needed files.#includes
shall be limited to what the header needs; other#includes
should be placed in the source file.
The first of the cross-referenced questions now includes a quote from the GSFC C coding standard, and the rationale, but the substance ends up being the same.
With regards to "Is there some way to undo [a using
declaration]?"
I think it is useful to point out that using
declarations are affected by scope.
#include <vector>
{ // begin a new scope with {
using namespace std;
vector myVector; // std::vector is used
} // end the scope with }
vector myOtherVector; // error vector undefined
std::vector mySTDVector // no error std::vector is fully qualified
So effectively yes. By limiting the scope of the using
declaration its effect only lasts within that scope; it is 'undone' when that scope ends.
When the using
declaration is declared in a file outside of any other scope it has file-scope and affects everything in that file.
In the case of a header file, if the using
declaration is at file-scope this will extend to the scope of any file the header is included in.
You are right that using namespace
in header is dangerous.
I do not know a way how to undo it.
It is easy to detect it however just search for using namespace
in header files.
For that last reason it is uncommon in real projects. More experienced coworkers will soon complain if someone does something like it.
In real projects people try to minimize the amount of included files, because the less you include the quicker it compiles. That saves time of everybody. However if the header file assumes that something should be included before it then it should include it itself. Otherwise it makes headers not self-contained.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With