Question

So, let's say I have a header like this:

#ifndef BASECLASS_H
#define BASECLASS_H

class BaseClass
{
    public:
        static int getX(){return x;}
    private:
        static int x;
};

int BaseClass::x = 10;

#endif

I have heard many times that I should not initialise static variables inside a header, but rather in cpp. But as there are guards, there should be only one copy of BaseClass::x. So I kinda do not understand why I should put

int BaseClass::x = 10; 

in cpp.

Was it helpful?

Solution

If you do it in the header, you'll get multiple definition errors as soon as you include it from more than one CPP file. You're really telling the compiler two things when you declare

int BaseClass::x = 10;

First, you're defining the symbol BaseClass::x; second you're telling it you want it to have the initial value of 10. According to the One Definition Rule this can only happen once in your program.

OTHER TIPS

Maybe it's easier to understand if you think about what the preprocessor actually does: It copies the content of all included header files into the cpp file and passes this to the compiler.

Now let's say you have:

// In a.cpp
#include <baseclass.h>

// more code

// In b.cpp
#include <baseclass.h>

// more code

After the preprocessor expands the includes, both files will contain:

int BaseClass::x = 10; 

Now as soon as both object files are passed to the linker, it will see the symbol BaseClass::x twice - which is an error.

Now, to make it even more obvious, imagine you would put this in a header file:

int aGlobalVariable = 10;

And then include it in two different cpp files, which should both be linked into one executable. It's actually not any different from your example, if seen from the linker's point of view.

Why is this not a problem with class declarations?

There's a difference between declarations and definitions. Only the latter will cause problems. E.g., all of the following are declarations:

  • extern int a;
  • void foo(int a);
  • class Foo { int bar(); };

Whereas these are definitions:

  • int a;
  • int b = 10;
  • void foo(int a) { /*..*/ }
  • int Foo::bar() { /*...*/ }

As long as there is one (and only one) definition, you can have as many declarations as you'd like, and the linker will make sure they all refer to the same function or memory location.

Now what about classes? Classes can only be declared, while their member functions and static members have to be defined. Again, each definition may only exist once.

Member functions and static members actually exist only once in a program's address space, whereas normal members (instance variables) exist for each object of the class.

Getting back to your specific problem: static members are basically just global variables, but scoped to the class' name.

Hope this clears things up for you!

The guards do not prevent multiple copies in multiple source files. They only prevent multiple copies in one source file.

You will be violating the one definition rule if you have multiple source files that #include "base_class.h".

Because If you initialize it in the header there is a possibility that it would be defined in multiple locations if you include the header more than once. Which will result in a linker error

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top