【问题标题】:What's the purpose of: "using namespace"?“使用命名空间”的目的是什么?
【发布时间】:2011-05-20 13:41:48
【问题描述】:

有令人信服的论点againstusing namespace std,那么为什么将它引入到语言中呢? using namespace 不会破坏命名空间的目的吗?我为什么要写using namespace?有什么我不知道的问题被using namespace 优雅地解决了,也许是using std::swap 成语或类似的东西?

【问题讨论】:

  • 少打字是一个非常诱人的论点......
  • 使用 'using' 的概念是围绕或反对命名空间,但当你需要它时它就在那里。
  • 另见 Herb Sutter 的 "Migrating to Namespaces."
  • @James:我有点不同意那篇文章 :) 由于在语言中引入了命名空间,现有代码从未中断,因为同时更改了头文件的命名约定。因此,如果您的旧代码使用#include <iostream.h>,那么cincout 在没有std:: 资格的情况下工作得很好。所以迁移代码绝对不是我的理由。
  • @Fred:所以,忽略短期解决方案。 “完全避免使用指令,尤其是在头文件中”和“永远不要在头文件中使用声明编写命名空间”的正确长期解决方案是极好的建议。

标签: c++ namespaces using-directives


【解决方案1】:

引入using namespace 的主要原因是向后兼容性:如果您有大量使用大量(标准前版本)标准库函数和类的前命名空间代码,您需要一种简单的方法来制作该代码使用符合标准的编译器。

顺便说一句,至少对于 C++98 而言,依赖于参数的查找规则意味着 using namespace std::rel_ops不会在模板中做你想做的事情(我不知道这是否在以后的版本中改变了标准)。

例子:

template<typename T> bool bar(T t)
{
  return t > T();
}

namespace foo
{
  class X {};
  bool operator<(X, X);
}

using namespace std::rel_ops;

int main()
{
  X x;
  bar(x); // won't work: X does not have operator>
}

请注意,将 using namespace 放入 namespace foo 也无济于事。

但是,在正确的位置使用 declarations 帮助:

template<typename T> bool bar(T t)
{
  return t > T();
}

namespace foo
{
  class X {};
  bool operator<(X, X);
  using std::rel_ops::operator>;
}

int main()
{
  X x;
  bar(x); // now works: operator> found per ADL via the using declaration in `namespace foo`
}

【讨论】:

    【解决方案2】:

    “命名空间允许在一个名称下对类、对象和函数等实体进行分组。这种方式可以将全局范围划分为“子范围”,每个子范围都有自己的名称。其中 identifier 是任何有效的标识符,实体是命名空间中包含的类、对象和函数的集合"

    更多信息在这里: http://www.cplusplus.com/doc/tutorial/namespaces/

    【讨论】:

      【解决方案3】:

      我发现它在使用具有深度嵌套命名空间的库时很有用。 Boost 库就是这样一个例子。到处都是boost::numeric::ublas::matrix&lt;double&gt; m的成像打字...

      要避免的事情是在头文件中使用using namespace,因为这可能会严重破坏包含该头文件的任何程序。始终将 using namespace 语句放在 .cpp/.cxx 文件中,使其仅限于文件范围。

      【讨论】:

      • 但是命名空间别名也可以解决这个问题。或者您可以只选择性地导入matrix
      • 或者你可以使用 typedef,例如typedef boost::numeric::ublas::matrix&lt;double&gt; DoubleMatrix 并在其余代码中使用 DoubleMatrix。这就是 C++ 的魅力/诅咒:有几种方法可以解决同一个问题。
      【解决方案4】:

      人们特别反对using namespace std;,但不反对using namespace BigCorp;或者参考std::cout(它使用命名空间,而不是using,如果你知道我的意思的话。)另外,大多数反对using namespace std 的地方都在头文件中。在可以立即看到效果的源文件中,它的危害性较小。

      命名空间是一个非常有用的概念,它允许我拥有一个名为 Date 的类,即使我正在使用的一个库有一个名为 Date 的类。在将它们添加到语言中之前,我们必须拥有 GCDateGCString 之类的东西(我的公司 Gregory Consulting 早于 std::string)。使用命名空间(有或没有using 关键字)让我们都可以编写更干净、更整洁的代码。但是当你每次都必须说Gregcons::string 时,你有点失去了更干净、更整洁的部分。 [免责声明:我实际上不再使用我自己的字符串类 - 想象一些适当的名称冲突。] 这就是 using 声明的吸引力。把它放在标题之外,不要把它应用到std,你通常应该远离麻烦。

      【讨论】:

      • 我会说,不要使用using namespace foo,而是使用using foo::whatever;这适用于标准名称和其他名称。例如,using std::cout 如果不在标头中完成,则没有任何问题。
      【解决方案5】:

      一方面,这是在命名空间中使用运算符重载的方式(例如 using namespace std::rel_ops;using namespace boost::assign;

      简洁也是一个强有力的论据。你真的会喜欢打字和阅读std::placeholders::_1而不是_1吗?此外,当您以函数式风格编写代码时,您将在 stdboost 命名空间中使用无数对象。

      另一个重要的用途(虽然通常不导入整个命名空间)是启用参数相关的查找:

      template <class T>
      void smart_swap(T& a, T& b)
      {
          using std::swap;
          swap(a, b);
      }
      

      如果交换在与 T 相同的命名空间中为某种类型的 T 重载,这将使用该重载。如果您改为显式调用std::swap,则不会考虑该重载。对于其他类型,这会退回到std::swap

      顺便说一句,using 声明/指令不会违背命名空间的目的,因为您始终可以完全限定名称以防出现歧义。

      【讨论】:

      • 就我个人而言,我对“使用 ”以及我遇到问题的“使用命名空间 ”感到满意(有一些例外,如 rel_ops)。
      【解决方案6】:

      大多数时候它只是编写代码的捷径。您可以将名称导入封闭的上下文中。我通常将其限制在 .cpp 文件中,因为当您将 using 指令包含到 .h 文件中时,它会污染包含它的所有文件。另一个好的做法是将using namespace 限制在尽可能封闭的环境中,例如,在方法主体声明内部。我认为它是一种方便,仅此而已,并且类似于命名空间别名,例如:

      namespace po = boost::program_options;
      

      然后你就可以写了

      po::variables_map ...
      

      【讨论】:

        猜你喜欢
        • 2011-03-23
        • 1970-01-01
        • 1970-01-01
        • 2016-03-11
        • 2022-01-19
        • 2011-04-24
        相关资源
        最近更新 更多