C ++:命名空间 – 如何正确使用头文件和源文件?

考虑一对两个源文件:一个接口声明文件( *.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() { ... } } 

我的问题:这两种做法是否有区别,是否被认为比另一种更好?

从代码可读性的angular度来看,在我看来,使用#2方法可能更好:

您可以一次using多个名称空间,并且在该行下面写入的任何对象或函数都可以属于任何这些名称空间(禁止命名冲突)。 将整个文件包装在namespace块中更加明确,并允许您在.cpp文件中声明属于该名称空间的新函数和variables

最明显的是你没有显示的选项:

 int MyNamespace::MyClass::foo() { // ... } 

这也很冗长; 对大多数人来说太多了。 由于using namespace是名称冲突的一个重要原因,至less在我的经验,应该避免,除非在有限的范围和地方,我通常使用#2。

这两种做法是否有区别?

是。 #1和#2分别是using-directive和namespace定义的例子。 在这种情况下,他们实际上是一样的,但有其他的后果。 例如,如果您在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的一个可能替代scheme是使用声明 ,其中只包含您感兴趣的标识符:

 #include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... } 

我还想补充一点,如果你决定由于某种原因在一个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方法,这将是罚款。

我想添加一个更多的方法,使用using声明

 #include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... } 

如果类有许多function,这样可以节省您多次input命名空间名称