未找到在未命名命名空间中声明的函数的函数定义 - 如何解决?(Visual Studio 2015)

sun*_*oon 5 c++ visual-studio-2015

我安装了 Visual Studio 2015并发现我的一些代码(在 VS 2013 中没有任何问题)现在出现了一些由绿色波浪线指示的错误(这应该是一个新的生产力功能)。但是代码仍然可以成功编译。

这是一个快速示例:

namespace
{
    void test1(); // what once was OK in VS 2013,
    void test2(); // is now marked with squiggles in VS 2015
}

namespace named
{
    void test3(); // OK, no problem
}

void        test1() { /*...*/ }
void      ::test2() { /*...*/ }
void named::test3() { /*...*/ }

int main() { /*...*/ }
Run Code Online (Sandbox Code Playgroud)

这些是有问题的波浪线

在此处输入图片说明

将鼠标移到它们上面告诉我

未找到“test1”的函数定义

未找到“test2”的函数定义


不知何故,只有在未命名命名空间内声明的函数才会触发波浪线。

应该如何解决?

Seb*_*edl 5

绿色曲线并不告诉您存在错误,而是告诉您新的重构工具有机会做一些事情。(红色曲线表示错误。)在这种情况下,它们通知您没有与 的声明匹配的定义test2,因此 IDE 会生成一个定义。

这恰好指出了代码中始终存在的错误,尽管 Visual Studio 的行为可能不符合要求。

那么会发生什么呢?问题是未命名命名空间中的声明没有声明您稍后在全局命名空间中定义的相同函数。重构工具认识到这一点并提供为声明的函数生成定义。

然而,由于微软编译器接受了两段严格非法的代码,整个程序仍然可以编译。首先,不允许在函数的第一个声明上使用命名空间前缀。then中的代码main大概会调用这些函数。正如 Alex M 在他的回答中所表明的那样,GCC 也不会接受这一点,因为该调用是不明确的。Microsoft 编译器似乎接受它,要么将定义视为与未命名命名空间中的声明匹配的定义(请记住,IDE、IntelliSense 和重构的工具,使用更兼容的 EDG 前端,而不是实际的解析器)编译器使用,这意味着重构可以说声明没有定义,而编译器将定义视为与声明匹配),或者只是更喜欢全局版本而不是命名空间版本。

顺便说一句,区分这两种情况很容易。重新排列代码,使其main位于函数定义之前。这将解决 GCC 中的歧义,因为仅声明了命名空间函数(而不是定义,因此您应该收到链接器错误)。如果它只是更喜欢全局版本,它还会导致 Microsoft 编译器中的链接器错误,但如果它将声明和定义视为匹配,则仍会编译。

解决这一切的方法非常简单:当定义在未命名命名空间中声明的函数时,只需重新打开命名空间,而不是尝试在外部定义函数。