'C++: Namespaces -- How to use in header and source files correctly?
Consider a pair of two source files: an interface declaration file (*.h
or *.hpp
) and its implementation file (*.cpp
).
Let the *.h
file be like the following:
namespace MyNamespace {
class MyClass {
public:
int foo();
};
}
I have seen two different practices for using namespaces in source files:
*.cpp
showing practice #1:
#include "MyClass.h"
using namespace MyNamespace;
int MyClass::foo() { ... }
*.cpp
showing practice #2:
#include "MyClass.h"
namespace MyNamespace {
int MyClass::foo() { ... }
}
My question: Are there any differences between these two practices and is one considered better than the other?
Solution 1:[1]
From a code readability standpoint, it is probably better in my opinion to use the #2 method for this reason:
You can be using
multiple namespaces at a time, and any object or function written below that line can belong to any of those namespaces (barring naming conflicts). Wrapping the whole file in a namespace
block is more explicit, and allows you to declare new functions and variables that belong to that namespace within the .cpp file as well
Solution 2:[2]
The clearest is the option you didn't show:
int MyNamespace::MyClass::foo()
{
// ...
}
It's also very verbose; too much so for most people. Since using namespace
is a recipe for name conflicts, at least in my experience,
and should be avoided except in very limited scopes and places, I
generally use your #2.
Solution 3:[3]
Are there any differences between these two practices
Yes. #1 and #2 are examples of a using-directive and a namespace definition respectively. They are effectively the same in this case but have other consequences. For instance, if you introduce a new identifier alongside MyClass::foo
, it will have a different scope:
#1:
using namespace MyNamespace;
int x; // defines ::x
#2:
namespace MyNamespace {
int x; // defines MyNamespace::x
}
is one considered better than the other?
#1 Pros: a little more terse; harder to accidentally introduce something into MyNamespace
unwittingly. Cons: may pull in existing identifiers unintentionally.
#2 Pros: more clear that definitions of existing identifiers and declarations of new identifiers both belong to MyNamespace
. Cons: easier to unintentionally introduce identifiers to MyNamespace
.
A criticism of both #1 and #2 is that they are referring to an entire namespace when you probably only care about the definition of members of MyNamespace::MyClass
. This is heavy-handed and it communicates the intent poorly.
A possible alternative to #1 is a using-declaration which includes only the identifier you're interested in:
#include "MyClass.h"
using MyNamespace::MyClass;
int MyClass::foo() { ... }
Solution 4:[4]
I'd like also to add that if you decide due to some reason to implement a template specialization in a cpp file and just rely on using namespace
you will run into the following problem:
// .h file
namespace someNameSpace
{
template<typename T>
class Demo
{
void foo();
};
}
// .cpp file
using namespace someNameSpace;
template<typename T>
void Demo<T>::foo(){}
// this will produce
// error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive]
template<>
void Demo<int>::foo(){}
Otherwise if you apply #2 method this will be fine.
Solution 5:[5]
I think the practice #1 is not correct C++ code at all. This code snippet defines ::MyClass::foo symbol, where the real full qualified name is ::MyNamespace::MyClass::foo.
To learn about namespaces you can read section 7.3 of the draft let's say for standard http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf
This concept is pretty old from 1998 or so, so you can use any standard or books of B.Stroustroup to learn about it.
In C++ language the namespace is a named scope. The namespace, as opposed to the class definition, is open to adding new functions to it.
The construction "using namespace NS;" in C++ is called as using-directive, and it can be used for several goals in my practice:
- You can use this directive in another namespace to combine(mix) names from a different namespace.
- In the context of the compilation unit it appends synonyms to all variables in namespace NS.
To define symbol, you can use two mechanisms - you can use the explicit qualification with all namespaces via operating in global namespace in C++ source file.
Or You can open namespace and add definitions to it (practice #2).
Solution 6:[6]
I'd like to add one more way, using a using-declaration:
#include "MyClass.h"
using MyNamespace::MyClass;
int MyClass::foo() { ... }
This saves you from typing the namespace name many times, if a class has many functions.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Dan F |
Solution 2 | codeling |
Solution 3 | |
Solution 4 | Jordan |
Solution 5 | Konstantin Burlachenko |
Solution 6 | codeling |