对静态成员的未定义引用
Posted
技术标签:
【中文标题】对静态成员的未定义引用【英文标题】:Undefined reference to a static member 【发布时间】:2012-02-02 10:12:57 【问题描述】:我正在使用交叉编译器。我的代码是:
class WindowsTimer
public:
WindowsTimer()
_frequency.QuadPart = 0ull;
private:
static LARGE_INTEGER _frequency;
;
我收到以下错误:
对 `WindowsTimer::_frequency' 的未定义引用
我也试过改成
LARGE_INTEGER _frequency.QuadPart = 0ull;
或
static LARGE_INTEGER _frequency.QuadPart = 0ull;
但我仍然遇到错误。
有人知道为什么吗?
【问题讨论】:
undefined reference for static member, linker error 的可能重复项 你在哪里(如果有的话)定义WindowsTimer::_frequency
?
@CharlesBailey 这是我班上唯一的成员。
【参考方案1】:
您需要在.cpp 文件中定义_frequency
。
即
LARGE_INTEGER WindowsTimer::_frequency;
【讨论】:
我为什么要这样做? @nowox 因为 C++ 不是 C#...静态数据成员基本上是一个全局变量,恰好位于其类的命名空间中。类定义中的 declaration 就像一个全局变量的 extern declaration:它宣布它的存在、名称和类型,但不创建对象(因为那时,你将在每个文件中都有一个对象,其中包含带有类定义的标头,与所需的相反)。相反,在其中一个 cpp 文件中有该对象的确切 一个 定义,并且链接器将使用该名称将代码解析为该对象。 @nowox 因此,在 C++17 之前需要单独的对象定义的原因与 C++ 过时的构建范例有关:它使用 1970 年代的“翻译单元”(peprocessing 后的文件)的想法,被单独编译成具有稀疏信息(例如,没有类型信息等)的目标文件。链接阶段与语言无关(例如,对 C++ 一无所知)并且与编译阶段分开。 (ctd.) (ctd) 相比之下,Java 或 C# 等环境会产生更多“语义丰富”的编译工件(类、包),通常同时来自多个源文件:允许不同文件中的代码更好地交互。【参考方案2】:使用 C++17,您可以声明变量inline,不再需要在 cpp 文件中定义它。
inline static LARGE_INTEGER _frequency;
【讨论】:
【参考方案3】:链接器不知道在哪里为_frequency
分配数据,您必须手动告诉它。您可以通过简单地将这一行:LARGE_INTEGER WindowsTimer::_frequency = 0;
添加到您的 C++ 源代码之一中来实现这一点。
更详细的解释here
【讨论】:
【参考方案4】:如果在类中声明了一个静态变量,那么你应该像这样在 cpp 文件中定义它
LARGE_INTEGER WindowsTimer::_frequency = 0;
【讨论】:
【参考方案5】:这是this other question 的完整代码示例,确实是这个的副本。
#include <iostream>
#include <vector>
using namespace std;
class Car
public:
static int b; // DECLARATION of a static member
static char* x1(int x)
b = x; // The static member is used "not as a constant value"
// (it is said ODR used): definition required
return (char*)"done";
;
int Car::b; // DEFINITION of the static
int main()
char* ret = Car::x1(42);
for (int x = 0; x < 4; x++)
cout << ret[x] << endl;
return 0;
【讨论】:
感谢您的回答。你能否分享一个链接,我可以在其中阅读更多关于静态成员函数(重要)和静态变量(我已经看过很多)的信息。其中包含更多详细信息和静态函数示例以及类的伪造静态构造函数以上是关于对静态成员的未定义引用的主要内容,如果未能解决你的问题,请参考以下文章