Visual C:命名空间范围错误或晦涩功能?

Visual C: Namespace Scope Bug or Obscure Feature?

本文关键字:功能 错误 命名空间 范围 Visual      更新时间:2023-10-16

您将需要三个不同的文件:header.hsource.cppmain.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

代码由工具生成。

谢谢

当你这样做时:

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::gmain.cpp没有尝试调用它(因为它不知道它的存在(。

因此链接器错误。

首先,请记住,main.cpp看不到任何source.cpp,所以它不知道其中声明/定义的实际void A::g()函数!

main.cpp看到的是一个命名空间Ausing namespace B。因此,当main.cpp调用A::g()时,编译器只能假设您引用void A::B::g()- 因此将其标记为要链接的函数。

但是,正如链接器正确诊断的那样,您尚未为此函数提供定义- 因此无法解析。