c++:名称空间——如何正确使用头文件和源文件?

时间:2022-10-25 15:08:15

Consider a pair of two source files: an interface declaration file (*.h or *.hpp) and its implementation file (*.cpp).

考虑一对两个源文件:接口声明文件(* .h或* .hpp)及其实现文件(* .cpp)。

Let the *.h file be like the following:

让* .h文件如下所示:

namespace MyNamespace {
  class MyClass {
  public:
    int foo();
  };
}

I have seen two different practices for using namespaces in source files:

我在源文件中看到了两种不同的使用命名空间的做法:

*.cpp showing practice #1:

* .cpp显示练习#1:

#include "MyClass.h"
using namespace MyNamespace;

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

*.cpp showing practice #2:

* .cpp显示练习#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?

我的问题:这两种做法之间是否有任何差异,哪一种被认为比另一种更好?

5 个解决方案

#1


46  

From a code readability standpoint, it is probably better in my opinion to use the #2 method for this reason:

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

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

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

#2


38  

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.

它也非常冗长;对大多数人来说太过分了。因为使用命名空间是名称冲突的接收,至少在我的经验中,应该避免,除非在非常有限的范围和地方,我通常使用你的#2。

#3


5  

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和#2分别是using-directive和namespace定义的示例。在这种情况下它们实际上是相同的但具有其他后果。例如,如果您在MyClass :: foo旁边引入一个新标识符,它将具有不同的范围:

#1:

#1:

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

#2:

#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.

#1优点:稍微简洁一点;更难以在不知不觉中意外地将某些内容引入MyNamespace。缺点:可能会无意中引入现有标识符。

#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.

#2优点:更清楚的是现有标识符的定义和新标识符的声明都属于MyNamespace。缺点:更容易无意中将标识符引入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.

对#1和#2的批评是,当你可能只关心MyNamespace :: MyClass成员的定义时,它们指的是整个命名空间。这是严厉的,它很难传达意图。

A possible alternative to #1 is a using-declaration which includes only the identifier you're interested in:

#1的可能替代方法是using声明,其中仅包含您感兴趣的标识符:

#include "MyClass.h"
using MyNamespace::MyClass;

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

#4


3  

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:

我还想补充一点,如果由于某种原因决定在cpp文件中实现模板特化并且只依赖于使用命名空间,则会遇到以下问题:

// .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.

否则,如果您应用#2方法,这将没有问题。

#5


0  

I'd like to add one more way, using using-declaration:

我想使用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

如果类具有许多功能,这种方式可以避免多次键入命名空间名称

#1


46  

From a code readability standpoint, it is probably better in my opinion to use the #2 method for this reason:

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

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

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

#2


38  

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.

它也非常冗长;对大多数人来说太过分了。因为使用命名空间是名称冲突的接收,至少在我的经验中,应该避免,除非在非常有限的范围和地方,我通常使用你的#2。

#3


5  

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和#2分别是using-directive和namespace定义的示例。在这种情况下它们实际上是相同的但具有其他后果。例如,如果您在MyClass :: foo旁边引入一个新标识符,它将具有不同的范围:

#1:

#1:

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

#2:

#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.

#1优点:稍微简洁一点;更难以在不知不觉中意外地将某些内容引入MyNamespace。缺点:可能会无意中引入现有标识符。

#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.

#2优点:更清楚的是现有标识符的定义和新标识符的声明都属于MyNamespace。缺点:更容易无意中将标识符引入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.

对#1和#2的批评是,当你可能只关心MyNamespace :: MyClass成员的定义时,它们指的是整个命名空间。这是严厉的,它很难传达意图。

A possible alternative to #1 is a using-declaration which includes only the identifier you're interested in:

#1的可能替代方法是using声明,其中仅包含您感兴趣的标识符:

#include "MyClass.h"
using MyNamespace::MyClass;

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

#4


3  

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:

我还想补充一点,如果由于某种原因决定在cpp文件中实现模板特化并且只依赖于使用命名空间,则会遇到以下问题:

// .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.

否则,如果您应用#2方法,这将没有问题。

#5


0  

I'd like to add one more way, using using-declaration:

我想使用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

如果类具有许多功能,这种方式可以避免多次键入命名空间名称