考虑一对两个源文件:接口声明文件(*.h
或*.hpp
)及其实现文件(*.cpp
)。
让*.h
文件如下所示:
namespace MyNamespace {
class MyClass {
public:
int foo();
};
}
我在源文件中看到了两种不同的使用命名空间的做法:
*.cpp
显示练习#1:
#include "MyClass.h"
using namespace MyNamespace;
int MyClass::foo() { ... }
*.cpp
展示练习#2:
#include "MyClass.h"
namespace MyNamespace {
int MyClass::foo() { ... }
}
我的问题:这两种做法之间是否有任何差异,哪一种被认为比另一种更好?
答案 0 :(得分:52)
从代码可读性的角度来看,我认为最好使用#2方法:
您一次可以using
个多个名称空间,并且在该行下面写的任何对象或函数都可以属于任何这些名称空间(除非命名冲突)。将整个文件包装在namespace
块中更加明确,并允许您在.cpp文件中声明属于该命名空间的新函数和变量
答案 1 :(得分:43)
最清楚的是您没有显示的选项:
int MyNamespace::MyClass::foo()
{
// ...
}
它也非常冗长;对大多数人来说太过分了。由于using
namespace
是对名称冲突的接受,至少在我的经验中,
应该避免,除非在非常有限的范围和地方,我
一般用你的#2。
答案 2 :(得分:6)
这两种做法之间是否有任何差异
是。 #1和#2分别是using-directive和namespace definition的示例。在这种情况下它们实际上是相同的但具有其他后果。例如,如果您在MyClass::foo
旁边引入新标识符,则它将具有不同的范围:
#1:
using namespace MyNamespace;
int x; // defines ::x
#2:
namespace MyNamespace {
int x; // defines MyNamespace::x
}
被认为比另一个好吗?
#1优点:稍微简洁一点;在不知不觉中不小心将某些东西引入MyNamespace
。缺点:可能会无意中引入现有标识符。
#2优点:更清楚的是现有标识符的定义和新标识符的声明都属于MyNamespace
。缺点:更容易无意中将标识符引入MyNamespace
。
对#1和#2的批评是,当你可能只关心MyNamespace::MyClass
成员的定义时,它们指的是整个命名空间。这是严厉的,它很难传达意图。
#1的可能替代方案是using-declaration,其中仅包含您感兴趣的标识符:
#include "MyClass.h"
using MyNamespace::MyClass;
int MyClass::foo() { ... }
答案 3 :(得分:4)
我还要补充一点,如果您因为某种原因决定在cpp文件中实现模板专精而只依赖using namespace
,则会遇到以下问题:
// .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(){}
否则,如果您应用#2方法,这将没问题。
答案 4 :(得分:0)
我想再添加一种方法,使用 using-declaration :
#include "MyClass.h"
using MyNamespace::MyClass;
int MyClass::foo() { ... }
这样,如果类有很多函数,这种方法可以避免多次输入命名空间名称