以下C++测试代码没有链接(gcc 4.9.2,binutils 2.25).错误是In function 'main': undefined reference to 'X::test'
.
01: #include02: #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
指令.
该指令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
指令.
using namespace
表示您使用您指定的命名空间中的定义,但这并不意味着您定义的所有内容都是在您使用的命名空间中定义的.
这种行为的逻辑非常简单.假设我们有以下示例:
namespace X { extern string test; }; namespace Y { extern string test; }; using namespace X; using namespace Y; string test = "value";
按照您的示例逻辑,编译器就不知道它应该在哪个命名空间中定义test
,因此您必须明确声明命名空间.在现实生活中,它在全局命名空间中定义.
在您的特定情况下,您可以在声明它test
的X
名称空间之外定义变量extern
.链接器查找X::test
但未找到的定义,因此您会看到此错误.