问题
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?
回答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
回答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 recepe for name conflicts, at least in my experience,
and should be avoided except in very limited scopes and places, I
generally use your #2.
回答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() { ... }
回答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.
回答5:
I'd like to add one more way, using using-declaration:
#include "MyClass.h"
using MyNamespace::MyClass;
int MyClass::foo() { ... }
This way saves you from typing namespace name many time if class have many functions
来源:https://stackoverflow.com/questions/10816600/c-namespaces-how-to-use-in-header-and-source-files-correctly