Poperton
Poperton

Reputation: 1796

Why static data members must be defined in C++?

I always struggle to discover why I'm getting "Undefined reference to static variable" in my code, and I always end up in these questions:

Undefined reference to static variable c++

Undefined reference to static variable

I understand that I need to define my data outside the class declaration.

In the example:

class Helloworld {
  public:
     static int x;
     void foo();
};

int Helloworld::x = 0; // Or whatever is the most appropriate value
                       // for initializing x. Notice, that the
                       // initializer is not required: if absent,
                       // x will be zero-initialized.

I must initiate x to some value. But what about static members that are class instances? Why simply the compiler won't make an instance for me with the default constructor?

If I write

class A {
    public: 
        B b;
}

then I can do

A a;
a.b;

I don't need to define B b outside the A class declaration. Why do I need to do it for the static example below?

class A {
    public: 
        static B b;
}

B A::b

Upvotes: 2

Views: 801

Answers (3)

Pedro LM
Pedro LM

Reputation: 750

You need to define B outside the class for the same reason you have to define x outside the class: because it’s a static member. Being a primitive type (int) or class type (B) has nothing to do with it!

Upvotes: -1

But what about static members that are class instances? Why simply the compiler won't make an instance for me with the default constructor?

But make it where? The rational for this prior to C++17 was that there must be only one such definition of the static member under the one definition rule. So it was up to the programmer to specify exactly in which translation unit that definition should live, even if the object was to undergo default initialization. The compiler wasn't trusted to "do the right thing"TM.

As compilers got smarter, and C++17 came about, it turned out that compilers really can be made to figure it out. In C++17 you can specify the static member as an inline variable, and the compiler/linker will sort it out.

class A {
    public: 
        static inline B b; // There, an inline variable default initialized.
};

Upvotes: 6

Michael Chourdakis
Michael Chourdakis

Reputation: 11178

Static members exist before any object is created, that is what makes them static. Therefore their initialization does not happen on first instance, they are there already.

They are actually global variables within a class scope.

That said, you can use the inline modifier to initialize them inside the class without an out of class declaration.

Info here and here.

Upvotes: 5

Related Questions