Visual C:命名空间范围错误或晦涩难懂的功能?
Posted
技术标签:
【中文标题】Visual C:命名空间范围错误或晦涩难懂的功能?【英文标题】:Visual C: Namespace Scope Bug or Obscure Feature? 【发布时间】:2019-10-03 16:43:34 【问题描述】:您将需要三个不同的文件:header.h
、source.cpp
和 main.cpp
。
// header.h
#pragma once
namespace A
namespace B
class C
public: static void f();
;
void g();
using namespace B;
// source.cpp
#include "Header.h"
namespace A
void C::f()
#pragma message( "Compiling " __FUNCTION__ )
void g()
#pragma message( "Compiling " __FUNCTION__ )
// main.cpp
#include "Header.h"
int main()
A::C::f();
A::g();
我预计没有错误,而是看起来类和函数属于不同的命名空间,尽管在同一范围内声明和实现:
1 > Source.cpp
1 > Compiling A::B::C::f
1 > Compiling A::g
1 > Generating Code...
1 > ConsoleApplication10.obj : error LNK2019 : unresolved external symbol "void __cdecl A::B::g(void)" ( ? g@B@A@@YAXXZ) referenced in function _main
代码由工具生成。
谢谢
【问题讨论】:
【参考方案1】:当你这样做时:
void C::f()
#pragma message( "Compiling " __FUNCTION__ )
这里的f
是一个限定名(由C
限定)。因此,C++ 必须弄清楚你在说什么C
。为此,它必须查看可用的非限定名称并在其中找到标识符C
。因为您在命名空间A
中,并且命名空间A
已将所有命名空间B
转储到其中,所以C
将解析为A::B::C
。因此,C::f
变为 A::B::C::f
。
相比之下,当你这样做时:
void g()
#pragma message( "Compiling " __FUNCTION__ )
g
是一个非限定名称。因此,该名称的含义正是它所说的:当前命名空间中的名称g
。这是A
。
using
声明不会改变当前命名空间;它只会更改名称的名称查找规则。因为g
是一个不合格的名字,所以没有什么可查的;你的意思是A::g
。
这意味着您没有定义函数A::B::g
。
所以你所拥有的是一个标题,上面写着“我保证有人会在某个地方定义A::B::g
”,但实际上没有人这样做。 source.cpp
只定义了A::g
,main.cpp
并没有尝试调用它(因为它不知道它的存在)。
因此出现链接器错误。
【讨论】:
我只是想在我的答案中添加关于A::B::C::f()
的内容,但不知道怎么做!你做得很漂亮 - 请给我点赞,先生!【参考方案2】:
首先,请记住main.cpp
看不到source.cpp
,所以它不知道其中声明/定义的实际void A::g()
函数!
main.cpp
所做的 看到的是一个 命名空间 A
,即using namespace B
。因此,当main.cpp
调用A::g()
时,编译器只能假设您引用void A::B::g()
- 从而将其标记为要链接的函数。
但是,正如链接器正确诊断的那样,您没有为此函数提供定义 - 所以它没有得到解决。
【讨论】:
以上是关于Visual C:命名空间范围错误或晦涩难懂的功能?的主要内容,如果未能解决你的问题,请参考以下文章
窗体头文件中的“错误 C2653:系统不是类或命名空间名称”,Visual C++
Visual Studio 2010 在编译 C++/CLI 项目时出现奇怪的错误
阻止 Visual Studio 将 using 指令放在命名空间之外