101

I'm using a cross compiler. My code is:

class WindowsTimer{
public:
  WindowsTimer(){
    _frequency.QuadPart = 0ull;
  } 
private:
  static LARGE_INTEGER _frequency;
};

I get the following error:

undefined reference to `WindowsTimer::_frequency'

I also tried to change it to

LARGE_INTEGER _frequency.QuadPart = 0ull;

or

static LARGE_INTEGER _frequency.QuadPart = 0ull;

but I'm still getting errors.

anyone knows why?

Raktim Biswas
  • 3,833
  • 5
  • 22
  • 29
kakush
  • 2,836
  • 14
  • 43
  • 63

4 Answers4

115

You need to define _frequency in the .cpp file.

i.e.

LARGE_INTEGER WindowsTimer::_frequency;
Ed Heal
  • 55,822
  • 16
  • 77
  • 115
  • 2
    Why should I do it so? – nowox Oct 08 '20 at 21:29
  • 1
    @nowox Because C++ is not C#... a static data member is basically a global variable that just happens to be in the namespace of its class. The *declaration* inside the class definition is like an extern *declaration* of a global variable: It announces its existence, name and type, but does not create the object (because then, you would have an object in every file which includes the header with the class definition, the opposite of what's desired). Instead, there is exactly *one* definition of that object in one of the cpp files, and the linker will resolve code using that name to that object. – Peter - Reinstate Monica Mar 22 '21 at 12:10
  • 1
    @nowox So the reason you needed a separate object definition before C++17 is related to the antiquated build paradigm of C++: It uses the 1970s idea of "translation units" (files after peprocessing) that are compiled separately into object files with sparse information (e.g. no type information etc.). The link stage is language agnostic (e.g., knows nothing about C++) and separate from the compilation stage. (ctd.) – Peter - Reinstate Monica Mar 22 '21 at 12:18
  • 1
    (ctd) Environments like Java or C#, by contrast, produce more "semantically enriched" compilation artifacts (classes, packages), typically from several source files at once: Compilation and linking are not clearly separated which allows better interaction between code in different files. – Peter - Reinstate Monica Mar 22 '21 at 12:23
41

With C++17, you can declare your variable inline, no need to define it in a cpp file any more.

inline static LARGE_INTEGER _frequency;
Zhenxiao Hao
  • 5,975
  • 7
  • 25
  • 46
39

Linker doesn't know where to allocate data for _frequency and you have to tell it manually. You can achieve this by simple adding this line: LARGE_INTEGER WindowsTimer::_frequency = 0; into one of your C++ sources.

More detailed explanation here

Community
  • 1
  • 1
Vyktor
  • 19,006
  • 5
  • 53
  • 93
25

If there is a static variable declared inside the class then you should define it in the cpp file like this

LARGE_INTEGER WindowsTimer::_frequency = 0;
Raghuram
  • 3,787
  • 2
  • 16
  • 24