在命名空间内使用声明的范围

Bre*_*and 43 c++ scope namespaces using

在C++头文件中是否安全(和正确)以在命名空间中使用using声明,如下所示:

#include <boost/numeric/ublas/vector.hpp>
namespace MyNamespace {
    using boost::numeric::ublas::vector;
    vector MyFunc(vector in);
}
Run Code Online (Sandbox Code Playgroud)

即,正确地包含在MyNamespace块中的"使用boost :: numeric :: ublas :: vector",还是会污染包含此标头的任何文件的命名空间?

ltj*_*jax 39

不,它不安全 - 它不会污染另一个命名空间,但由于其他原因它是危险的:

一个using指令将导入任何当前可见由你指定到您使用它的命名空间的名称.虽然using只有用户MyNamespace可以看到您的内容,但您的using声明中会显示"外部"的其他内容.

那么在标题中使用时这有多危险?因为它将导入在声明点处可见的内容,所以确切的行为将取决于您在声明之前包含的标题的顺序(可能有不同的东西可见boost::numeric::ublas::vector).因为你无法真正控制在标题之前包含哪些标题(你也不应该!标题应该是自给自足的!),这可能导致非常奇怪的问题,你的函数会在一个编译单元中找到一个东西,而另一个在下一个.

根据经验,using只应在.cpp文件中的所有包含之后使用声明.在Sutter和Alexandrescu的"C++编码标准"一书中,这个问题还有一个问题(项目59).这里有一句话:"但这里是常见的陷阱:许多人认为使用在命名空间级别发布的声明(......)是安全的.它们不是.它们至少是危险的,并且以更微妙和更阴险的方式."

即使你using不可能在其他任何地方存在你的名字(这可能是这里的情况),事情也会变得丑陋:在标题中,所有声明都应该是完全限定的.这很痛苦,但除此之外,可能会发生奇怪的事情.

另请参阅迁移到命名空间,使用声明和命名空间别名以及命名空间命名以获取示例和深入描述的问题.

  • @ltjax:你究竟是什么意思暧昧?在`MyNamespace`里面,使用_declaration_引入的`vector`将隐藏使用_directive_引入的全局命名空间中可见的任何向量.当然这是意图吗? (4认同)
  • 我也一直在寻找方法来制作更具可读性的语法而不需要太多`std ::`前缀.在定义我的类之前,我真的想在我自己的命名空间中使用`using :: std :: vector`,以便代码读取更容易.我理解`使用命名空间'是有风险的,如果`using`声明函数,我可以理解这个问题.但据我所知,类型的唯一问题是如果"其他人"应该在我的命名空间中定义一个同名的类型,则可能会发生冲突.这真的是一个很大的问题,没有人使用这种模式? (4认同)
  • "这一点仍然有效." 也许,虽然我必须说我还没有看到类型的问题. (3认同)
  • 请注意,我使用`使用boost :: numeric :: ublas :: vector`,而不是`使用命名空间boost :: numeric :: ublas`,因为我不想导入整个`boost :: numeric :: ublas`命名空间.此外,因为这是在`命名空间MyNamespace {}`块中声明的,所以如果有人写了类似`using namespace std的东西,那么vector不应该是不明确的; 使用命名空间MyNamespace;`? (2认同)
  • @ltjax:总而言之,如果我在头文件中的命名空间块中使用`using :: boost :: numeric :: ublas :: vector`,这会避免我头文件中可能存在的歧义吗?如果有人后来调用`using namespace std; 在.cpp文件中使用命名空间MyNamespace`会导致歧义,但是``using namespace std; 使用命名空间boost :: numeric :: ublas;`...所以没有太大问题,是吗? (2认同)

Bjö*_*lex 12

正如名称所述,使用声明是一种声明.所有声明都限定在封闭块(7.2),在本例中为命名空间MyNamespace.它不会在该命名空间外可见.

  • "它不会在该命名空间之外可见." - 虽然这是正确的,但事实并非相反:使用指令可以看到外部内容,可能会改变您和其他人的代码的含义. (3认同)
  • @Brett:如果他们有一个`using namespace std;`你就会有一个名字冲突.我总是喜欢完全合格的名字.您始终可以为命名空间创建短别名. (2认同)

BЈо*_*вић 5

它是安全的,但它会污染 MyNamespace 命名空间。因此,任何包含该头文件的文件都将在 MyNamespace 中具有函数/类。

  • 但是 OP 只导入了一种类型,而不是整个命名空间。那是污染吗? (3认同)