【问题标题】:Linkage error for a header containing const variables and included in multiple files?包含 const 变量并包含在多个文件中的标头的链接错误?
【发布时间】:2020-03-11 10:41:01
【问题描述】:

我正在编写用于测试的代码,其中我有一个TestUtil.h,它定义了两个常量和一些函数。我将此头文件实现为TestUtil.cpp,还有第三个文件ActualTests.cpp,我正在其中编写实际测试。 TestUtil.hTestUtil.cpp 只是编写简洁测试的帮助文件。

我有嵌套的命名空间,TestUtil.h 看起来像这样:

namespace SNMPSubAgentTesting {

  namespace MibDataReaderTesting {

     const wchar_t* TEST_MUTEX_NAME = L"TestMutex";

     const wchar_t* TEST_MEMORY_NAME = L"TestMemory";

   //some functions 
   } 
}

在实现TestUtil.cpp我包含上面的头文件并给出实现:

#include "TestUtil.h"

 namespace SNMPSubAgentTesting {

  namespace MibDataReaderTesting {
     //implementations
  }
}

在第三个文件ActualTests.cpp 中,我再次包含TestUtil.h 以便使用实用功能:

#include "TestUtil.h"

 namespace SNMPSubAgentTesting {

  namespace MibDataReaderTesting {

     //Test class and tests
  }
}

编译器给出一个链接错误,并指出TestUtil.h 中的两个const 变量已在TestUtil.cpp 中定义,因此无法编译ActualTests.cpp。由于const 变量是内部链接的,我们可以在多个文件中包含包含const 变量的标头而不会出现链接错误,为什么在我的情况下它没有链接?是因为嵌套的命名空间吗?

编辑:我正在使用 Microsoft 单元测试框架进行测试。 const 变量在 MibDataReaderTesting 命名空间中,而不是在全局命名空间中。

我的源代码中有头文件,这些头文件包含在多个文件中,并且其中包含 const 变量。在这种情况下没有错误,但对于测试用例它给出了错误。黑白源代码和测试代码的唯一区别是测试框架和嵌套命名空间

【问题讨论】:

  • 您正在标题中的全局命名空间中定义对象。它们将在任何将它们拉入的翻译单元中按原样定义。它们是const 是无关紧要的。一种适当的解决方案是在标题 没有 指定初始值的情况下 extern 它们,然后将它们的实际定义放入具有初始值的 one 翻译单元中(因为它们是常量,永久)值。
  • @WhozCraig 但是在命名空间范围内声明的名称应该具有内部链接,如果它们是“...非易失性非模板(C++14 起)非内联(C++17 起)非导出(C++20 起)const 限定变量(包括 constexpr),未声明 extern 且之前未声明为具有外部链接”(强调我的)。这些变量在命名空间范围内,是 const 限定的,并且没有被声明为 extern 并且之前没有被声明为具有外部链接。 (引自en.cppreference.com/w/cpp/language/…)。
  • @WhozCraig 但变量是在 MibDataReaderTesting 命名空间内定义的。它们在全局命名空间中的情况如何?
  • 什么是编译器以及你编译的 C++ 版本是什么?
  • @MahanGM 这是 Visual Studio 中的 Visual C++ 和最新的 Windows SDK

标签: c++ visual-c++ namespaces constants linker-errors


【解决方案1】:

this internal linkage reference 中所述,const 限定名称具有内部链接。

问题是你的名字 const 合格。 const 是指针指向的数据,而不是变量本身。

您需要在正确的位置添加const

const wchar_t* const TEST_MUTEX_NAME = L"TestMutex";
//             ^^^^^
// Make TEST_MUTEX_NAME itself constant

【讨论】:

  • 这太疯狂了。我相信你的话,但我仍然没有在我做同样事情的其他代码部分中遇到链接错误。
  • @NavjotSingh 你是否同时拥有它们的低级和顶级常量?
  • @NavjotSingh 这就是重点。您要么没有指针类型,要么如果有,它们有一个顶级 const。多看几遍就明白了。
  • @NavjotSingh 解释了原因。第一个(低级)const 用于变量,第二个(顶级)const 用于指针。通过使指针为 const,编译器可以确保这个变量无论如何都不会改变,因此它可以用于内部链接和所有爵士乐。
  • @NavjotSingh 指针并没有什么特别之处,只是 const 的位置是相关的。 const char* p = "foo";p 定义为“指向char 的指针,即const”,并等效于char const* p = "foo;",其中p 是“指向constchar 的指针”。当你写const char* const p = "foo";然后你说“p是一个const指向char的指针,即const”。与指针相关的是“const指针”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多