对静态成员的未定义引用

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;

【讨论】:

感谢您的回答。你能否分享一个链接,我可以在其中阅读更多关于静态成员函数(重要)和静态变量(我已经看过很多)的信息。其中包含更多详细信息和静态函数示例以及类的伪造静态构造函数

以上是关于对静态成员的未定义引用的主要内容,如果未能解决你的问题,请参考以下文章

对静态类成员的未定义引用

通过添加 0 修复对静态成员变量的未定义引用

对静态 constexpr 数据成员的未定义引用错误

静态成员

静态成员

c++中对静态变量的未定义引用