如何正确定义已在标头中声明的名称空间内的实体?

问题描述 投票:0回答:6

考虑一对两个源文件:接口声明文件(

*.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() { ... }

}

我的问题:这两种做法之间有什么区别吗?一种被认为比另一种更好?

c++ namespaces header-files
6个回答
86
投票

从代码可读性的角度来看,我认为使用#2 方法可能更好,因为这个原因:

您可以同时成为多个命名空间,并且该行下方编写的任何对象或函数都可以属于任何这些命名空间(除非命名冲突)。将整个文件包装在

using
块中更加明确,并且允许您在 .cpp 文件中声明属于该命名空间的新函数和变量
    


64
投票

namespace

它也非常冗长;对于大多数人来说太多了。由于 
int MyNamespace::MyClass::foo() { // ... }

是名称冲突的根源,至少根据我的经验, 除非在非常有限的范围和地方,否则应该避免,我 一般使用你的#2。

    


12
投票
这两种做法有什么区别吗

是的。 #1 和 #2 分别是
using-directive

namespace定义的示例。在这种情况下,它们实际上是相同的,但会产生其他后果。例如,如果您在 using namespace 旁边引入一个新标识符,它将具有不同的范围:


#1:

MyClass::foo

#2:

using namespace MyNamespace; int x; // defines ::x

  
一个被认为比另一个更好吗?

#1 优点:更简洁一点;更难无意中无意间将某些东西引入
namespace MyNamespace { int x; // defines MyNamespace::x }

。缺点:可能会无意中引入现有标识符。


#2 优点:更清楚的是,现有标识符的定义和新标识符的声明都属于

MyNamespace

。缺点:更容易无意中引入标识符

MyNamespace

对 #1 和 #2 的批评是,当您可能只关心

MyNamespace

成员的定义时,它们指的是整个命名空间。这是一种严厉的做法,并且很难传达意图。


#1 的可能替代方案是

using-declaration

,其中仅包含您感兴趣的标识符: MyNamespace::MyClass



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

,您将遇到以下问题:


using namespace

否则如果你应用#2方法就可以了。


4
投票
using-declaration

: // .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(){}

如果一个类有很多函数,这可以避免您多次键入名称空间名称。


1
投票
实践#1

根本不是正确的C++代码。此代码片段定义了 ::MyClass::foo 符号,其中真正的完整限定名称是 ::MyNamespace::MyClass::foo。 要了解命名空间,您可以阅读草案的第 7.3 节,比如说标准

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf

这个概念从 1998 年左右就已经很老了,所以你可以使用 B.Stroustroup 的任何标准或书籍来了解它。

在 C++ 语言中,

namespace

是命名范围。与类定义相反,命名空间可以向其中添加新函数。 C++ 中的构造

“using namespace NS;”

称为 using 指令,在我的实践中它可以用于多个目标:

您可以在另一个命名空间中使用此指令来组合(混合)来自不同命名空间的名称。
  1. 在编译单元的上下文中,它将同义词附加到命名空间
  2. NS
  3. 中的所有变量。
  4. 要定义符号,您可以使用两种机制 - 您可以通过在 C++ 源文件中的全局命名空间中操作来对所有命名空间使用显式限定。

或者您可以打开名称空间并向其添加定义(练习#2)。

© www.soinside.com 2019 - 2024. All rights reserved.