5

I have a simple class for storing sensor data which can be summarized as

class Data
{
  public:
  Data(){timestamp = Time::now(); id = sNextID++; data = 0; type = DATA_TYPE_UNKNOWN;}

  double data;
  Time timestamp;
  DataType type;

  private:
  static unsigned int sNextID;
};

I have a header file that declares a bunch of similar data classes. Given the simplicity of the classes there is no need for an implementation cpp file.

The problem is, without an implementation file how do I initialize sNextID? I read somewhere that it defaults to 0 which would be fine, although relying on that seems a bit hackish. More importantly, though, without initializing it somewhere the linker complains of an undefined reference.

ryan0270
  • 1,135
  • 11
  • 33

2 Answers2

6

Use inline function (free-standing or member):

inline unsigned &sNextID()
{
    static unsigned data = 0;
    return data;
}

Or class template (defenition of it's statics can be in header file):

template<typename tag>
struct Foo
{
    static unsigned sNextID;
};

template<typename tag>
unsigned Foo<tag>::sNextID=0;

Update: In C++17 inline variables are available:

struct Foo
{
    static inline unsigned sNextID;
};
Evgeny Panasyuk
  • 9,076
  • 1
  • 33
  • 54
  • Oh, I like the template option. I haven't gotten around to using templates yet but I'm going to be moving in that direction anyhow. Thanks – ryan0270 Apr 07 '13 at 03:04
0

in the header file (let's say it's name is data.h), add this at the end

class Data
{
    .....
  private:
  static unsigned int sNextID;
};

#ifdef MY_INIT
unsigned int sNextID = 0;
#endif

in the file where you have main

#define MY_INIT
#include "data.h"

in all other files where you are including the header, just a plain

#include "data.h"

This will ensure that the line unsigned int sNextID = 0; will be compiled into only one translation unit - the one with main.

user93353
  • 13,733
  • 8
  • 60
  • 122