【问题标题】:c++: "Redeclare" extern namespace variables in .cppc++:“重新声明”.cpp 中的外部命名空间变量
【发布时间】:2019-09-30 10:09:13
【问题描述】:

我是 C++ 新手,偶然发现了这段代码:

文件.h

namespace Type
{
   typedef BOOL (WINAPI *TYCopyFile)
   (
    PCHAR lpExistingFileName,
    PCHAR lpNewFileName,
    BOOL  bFailIfExists
   );
}

namespace Func
{
  extern Types::TYCopyFile pCopyFileA;
}

文件.cpp

namespace Funcs
{
  Types::TYCopyFile pCopyFileA;
}

void Init
{
  Funcs::pCopyFileA = (Types::T_CopyFile) GetProcAddress(hKernel32, "CopyFileA");
}

这个想法真的很简单。我有typedef(Types) 的命名空间,并在另一个命名空间(Funcs) 中创建函数指针作为extern。然后我在Init函数中定义File.cpp中的函数指针。

我的问题是为什么我需要在File.cpp 中重新声明namespace Funcs?为什么我不能只使用Init 函数来初始化Funcs::pCopyFileA?据我了解extern,它告诉编译器该变量存在于某处并告诉链接器找到它。为什么链接器在File.cpp 中没有namespace Funcs 就找不到它?

【问题讨论】:

  • 当您使用extern 时,您承诺在您的翻译单元之一中定义变量。 stackoverflow.com/questions/10422034/when-to-use-extern-in-c
  • 我在void Init函数中定义了它们,为什么我在File.cpp中需要namespace Funcs
  • 这不是定义,而是分配。 (顺便说一下,这与在全局命名空间中的工作方式相同。)
  • 您没有在函数中定义它。您正在分配给它。
  • 您承诺定义的实际变量名称是 Funcs::pCopyFileA 命名空间是命名的一部分

标签: c++ windows visual-studio namespaces


【解决方案1】:

对于 C++ 中的所有符号,您都需要 声明定义。头文件包含Func::pCopyFileA的声明,源文件包含定义。

如果您在头文件中定义变量(即删除extern 关键字),那么定义将在所有包含头文件的translation units 中完成。这会破坏one definition rule,并在链接时导致多定义错误。

【讨论】:

  • 虽然他们可以使用inline 如果他们有 C++17 以便他们可以在头文件中定义和声明它。
  • 所以如果没有extern,我会多次重新定义同一个变量,对吗?
  • @user3503143 是的,没错。添加extern 关键字使其成为声明而不是定义。而且你可以声明一个变量你想要多少次(只要你声明它的方式相同)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-19
  • 1970-01-01
  • 2015-01-07
  • 2016-04-30
  • 1970-01-01
相关资源
最近更新 更多