在 C++ 中声明但未定义的静态函数

Posted

技术标签:

【中文标题】在 C++ 中声明但未定义的静态函数【英文标题】:Static function declared but not defined in C++ 【发布时间】:2012-06-04 11:32:10 【问题描述】:

我在使用 C++ 的以下代码中遇到错误。

Main.cpp

#include "file.h"

int main()

   int k = GetInteger();
   return 0;

文件.h

static int GetInteger();

文件.cpp

#include "file.h"

static int GetInteger()

   return 1;

我得到的错误:

Error C2129: static function 'int GetInteger(void)' declared but not defined.

我看过著名的文章"Organizing Code File in C and C++",但不明白这段代码有什么问题。

【问题讨论】:

你如何链接它? "gcc -o Test Main.cpp File.cpp -lstdc++" 或 XCode/VisualStudio/Eclipse 中的某处? @ViktorLatypov 说了什么。向我们展示你是如何编译它的。 @ViktorLatypov:我在 C++/CLI 项目中选择 Visual Studio 2013 中的文件并单击编译按钮时遇到了这个问题。 (C++ 按钮的编译按钮没有链接,也不应该遇到此错误,但也许 C++/CLI 不同?)(哦等等,刚刚看到最佳答案。我已将 static 类转换为命名空间>. 【参考方案1】:

改变

static int GetInteger();

int GetInteger();

static 在这种情况下给出了方法internal linkeage,这意味着您只能在定义它的翻译单元中使用它。

您在File.cpp 中定义它并尝试在main.cpp 中使用它,但main 没有它的定义,因为您声明了它static

【讨论】:

【参考方案2】:

在 C++ 中,static 在全局/命名空间范围内意味着函数/变量仅在定义它的翻译单元中使用,而不在其他翻译单元中使用。

在这里,您尝试使用来自不同翻译单元 (Main.cpp) 的静态函数,而不是定义它的翻译单元 (File.cpp)。

删除static,它应该可以正常工作。

【讨论】:

【参考方案3】:

声明为静态的函数是包含文件的本地函数。因此,您必须在与调用它的文件相同的文件中定义该函数。如果你想让它可以从其他文件中调用,你不能将它声明为静态的。

【讨论】:

【参考方案4】:

如果所有内容都在同一个翻译单元中,它应该可以工作。 您可能没有将 File.cpp 编译到与 Main.cpp 相同的单元中。

g++ -Wall File.cpp Main.cpp

如果每个文件都单独编译,则必须将函数设为 extern 才能从 不同的翻译单元。

extern int GetInteger();

相同
int GetInteger();

【讨论】:

他使用的是 Visual Studio,而不是 g++【参考方案5】:

因为在这种情况下,static 表示函数的名称有 内部联动;一个翻译单元中的GetInteger 不相关 到任何其他翻译单元中的GetInteger。关键字static 是 重载:在某些情况下,它会影响生命周期,而在其他情况下,会影响绑定。 这里特别令人困惑,因为“静态”也是一个名称 寿命。在命名空间范围内声明的函数和数据,总是 有静态生命周期;当static 出现在他们的声明中时,它 导致内部绑定,而不是外部绑定。

【讨论】:

【参考方案6】:

据我了解,静态函数的名称与定义它们的文件名混淆,因此当您在 main.cpp 中包含 file.h 时,尽管您在文件中定义了 GetInteger(),但 GetInteger() 会与 main.cpp 混淆.cpp 但由于它是静态的,因此它也会被破坏,并且链接器无法找到 GetInteger() 的定义,因为不存在此名称的函数。

我相信吸取的教训是不要在头文件中声明静态函数,因为它们不打算成为接口的一部分。

【讨论】:

【参考方案7】:

考虑使用命名空间...

用于不需要内部成员变量的代码逻辑部分。这意味着,您的 GetInteger() 函数不需要引用内部常量变量。为了使您的函数在代码中井井有条,请考虑使用命名空间。这可以防止函数名称发生冲突(这将节省您因可能出现的LNK 错误而头疼的时间)。该代码仍然按照您设置的方式工作,并且仍然在接受的答案范围内工作。此外,您的命名空间名称可以帮助您快速调试。

Main.cpp

#include "file.h"

int main()

   int k = HELPERS::GetInteger();
   return 0;

文件.h

namespace HELPERS

    int GetInteger();

文件.cpp

#include "file.h"

int HELPERS::GetInteger()

   return 1;

【讨论】:

以上是关于在 C++ 中声明但未定义的静态函数的主要内容,如果未能解决你的问题,请参考以下文章

C++ 静态成员函数

C++ 静态成员函数

C++ 静态成员函数

static

C++ 基本知识整理

C++类中的静态成员函数以及静态成员变量