首页 > 解决方案 > Visual C:命名空间范围错误或晦涩难懂的功能?

问题描述

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

代码由工具生成。

谢谢

标签: c++visual-c++namespacesc++17

解决方案


当你这样做时:

  void C::f()
  {
    #pragma message( "Compiling " __FUNCTION__ )
  }

这里f是一个限定名称(由 限定C)。因此,C++ 必须弄清楚C你在说什么。为此,它必须查看可用的非限定名称并C在其中找到标识符。因为您在 namespace 中A,并且 namespaceA已将所有命名空间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.cpponly defined A::g,它main.cpp不尝试调用(因为它不知道它存在)。

因此链接器错误。


推荐阅读