2

我和我的同事发生了争执。

我们有一个类,它是命名空间的成员(它是另一个命名空间的成员,但我认为这在这里并不重要)。在头文件中,我们将类块嵌套到命名空间块中,如下所示:

namespace NS {
    class A {
        void method();
        // ...
    };
}

这是 .cpp 文件和我们论证的主题。我写:

using namespace NS;

void A::method() {
    // ...
}

同事告诉我,我不正确地使用了 'using' 指令,我应该在这里使用与标题中相同的 NS { ... }。(他修改了代码并得到了一些编译器错误,他只能通过删除 using 指令并用 NS { ... } 包围代码来摆脱这些错误。)

我的观点是“使用”只会影响名称查找,因此在 NS 命名空间中查找 A,所以我的方法是正确的,他的编译器问题是由其他原因引起的,而不是由“使用”指令引起的。

谁是对的,为什么?

补充:伙计们,请不要像“我多次这样做(或那样)方式”那样回答,这没有多大用处。我们在这里需要理论:为什么这种或那种方法是对还是错。

4

6 回答 6

4

你的同事是正确的,你应该用命名空间包装 cpp,这意味着你在命名空间 NS 中定义你的功能。

namespace NS
{    
  void A::method() 
  {
    // ...
  }
}

如果您有多个 A 可用,您可能会得到冲突名称查找。

这里发生的危险事情是 using 声明会A::method在遇到 using 声明时对命名空间 NS 中命名的任何实体进行快照。

阅读有关命名空间的Google cpp 风格指南,以及101 个 c++ 编码标准

于 2013-01-31T02:34:19.760 回答
3

你们俩在不同的方面都是对的。你是对的, using 指令会让编译器解析Avoid A::method()be NS::A,但他也是对的,在大多数情况下你最好打开命名空间。

原因是不会查找标题中命名空间中声明的所有内容,并且对于这些元素,您需要打开命名空间(或手动提供限定),因此提供统一的方法是有意义的。

一个常见的示例是应用于类型的运算符的定义:

// header
namespace NS {
   class A { ... };
   std::ostream& operator<<(std::ostream&,A const&);
}
// implementation file (incorrect):
using namespace NS;
std::ostream& operator<<(std::ostream& o, A const & a) {
   // do something
}

这里的问题是函数定义(当函数名不是限定名时)是自我声明的。在标头中,运算符被声明为::NS::operator<<,但在实现文件中,它被定义为std::ostream& ::operator<<(std::ostream&, NS::A const&). using 指令将允许A标识符的解析为NS::A,但它不会使该函数定义驻留在NS命名空间中。

::NS::operator<<这导致了一个微妙的问题,由于 ADL,该运算符的任何使用都会发现,但该运算符在任何地方定义(尽管在不同的命名空间中有类似的运算符)

说了这么多,有一些编码约定(我现在工作的地方有这样的指导方针)要求所有类型的命名空间,并且自由函数定义应该在命名空间之外执行,并且总是有资格避免自我声明。在上面的示例中,操作符将在实现文件中定义为:

std::ostream& ::NS::operator<<(std::ostream& o, A const& a) { ... }

但是除非你真的习惯了总是限定条件,否则如果你忘记了函数的限定条件,这很容易出错。

于 2013-01-31T02:41:20.253 回答
1
namespace NS {
    class A {
        void method();
        // ...
    };
}

一直都是这样...

于 2013-01-31T02:34:24.540 回答
1

事实证明,这不仅仅是“编码风格的问题”。在头文件中定义和初始化声明为 extern 的变量时,使用命名空间 ... 会导致链接错误。看看我的问题中的例子。cpp文件中命名空间内常量的定义

于 2014-07-15T08:20:24.743 回答
0

你是对的。我已经被这个咬过很多次了(也就是说,被认为using声明不会这样做而被咬过)。您可以通过三种方式编写此代码,并且都可以:

namespace NS
{
    void A::method()
    { }
}

或者:

NS::A::method() { }

或者:

using namespace NS;

A::method() { }

但是,就风格而言,我建议第一个或第二个 -using当您有多个具有相同名称和方法的类时,声明可能会变得很麻烦。

于 2013-01-31T02:36:24.457 回答
0

最好不要在代码声明或库中使用“使用命名空间”,但可以将它们用于实际程序的代码。

即:不要将它用于 Cpp 定义,但您可以在外部调用函数/类时使用它。

这只是良好的编码实践,除非其他人正在使用您的代码,否则您想要什么更重要。

最好将 cpp 代码放入 Namespace { ... } 以提高可读性

于 2013-01-31T02:38:13.963 回答