当前位置:  开发笔记 > 编程语言 > 正文

"使用命名空间"到底做了什么?

如何解决《"使用命名空间"到底做了什么?》经验,为你挑选了2个好方法。

以下C++测试代码没有链接(gcc 4.9.2,binutils 2.25).错误是In function 'main': undefined reference to 'X::test'.

01: #include 
02: #include 
03:
04: namespace X
05: {
06:     extern std::string test;
07: };
08:
09: using namespace X;
10: std::string test = "Test";
11:
12: int main()
13: {
14:    std::cout << X::test << std::endl;
15: }

由于第09行,我期待第10行定义X::test在第06行声明的变量.我相信test在全局命名空间中声明和定义了一个不相关的变量,因此链接错误.

问题:有人可以解释为什么我的期望不正确,究竟发生了什么?

不是答案:

我可以将它改为第10行std::string X::test = "Test";.

我不应该使用"using namespace"开头.

Reinstate Mo.. 27

该指令using namespace X;使命名空间中X的名称在包含该指令的命名空间内可见.也就是说,在查找n该范围内的名称时,X::n可以找到.但是,只有在编译器需要查找它时才会查找它.

在您的示例中,此声明:

std::string test = "Test";

在全局命名空间内部完全有意义.test与任何其他声明一样,简单地引入了该名称.无需在任何地方查找.

这将是一个完全不同的鱼:

namespace X
{
  struct C
  {
    static std::string test;
  };
}

using namespace X;
std::string C::test = "Test";

在这段代码中,编译器需要知道什么C才能理解定义C::test.因此它进行了名称查找C,这确实X::C得益于该using指令.



1> Reinstate Mo..:

该指令using namespace X;使命名空间中X的名称在包含该指令的命名空间内可见.也就是说,在查找n该范围内的名称时,X::n可以找到.但是,只有在编译器需要查找它时才会查找它.

在您的示例中,此声明:

std::string test = "Test";

在全局命名空间内部完全有意义.test与任何其他声明一样,简单地引入了该名称.无需在任何地方查找.

这将是一个完全不同的鱼:

namespace X
{
  struct C
  {
    static std::string test;
  };
}

using namespace X;
std::string C::test = "Test";

在这段代码中,编译器需要知道什么C才能理解定义C::test.因此它进行了名称查找C,这确实X::C得益于该using指令.



2> Alex..:

using namespace表示您使用您指定的命名空间中的定义,但这并不意味着您定义的所有内容都是在您使用的命名空间中定义的.

这种行为的逻辑非常简单.假设我们有以下示例:

namespace X
{
    extern string test;
};

namespace Y
{
    extern string test;
};

using namespace X;
using namespace Y;

string test = "value";

按照您的示例逻辑,编译器就不知道它应该在哪个命名空间中定义test,因此您必须明确声明命名空间.在现实生活中,它在全局命名空间中定义.

在您的特定情况下,您可以在声明它testX名称空间之外定义变量extern.链接器查找X::test但未找到的定义,因此您会看到此错误.


@ marcv81:重点是当*定义*一个标识符*时,编译器不会"搜索"一个声明.(标识符不需要*在定义之前声明.)语句`std :: string test = ...`*在当前命名空间*中定义*变量`test`*,使用命名空间. ..`*不影响*; 它只影响*搜索*标识符的名称空间.标识符仅在*引用*时被"搜索" - *定义*不是.这正是亚历克斯试图说的.
@ marcv81:更好的风格是另一种方式,*总是*写'X ::`和*永远*写'使用命名空间X;`.实际上,后者是一个拐杖,因为它从信息来源中夺走了信息.(您无法分辨给定标识符来自哪个命名空间,这是一个皇家PITA在调试源代码时使用"使用命名空间"对其中的六个.如果命名空间名称太长而无法重复输入,请使用`namespace short = very :: long :: namespace;`和`short :: identifier`.
推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有