Static Variable in the Class Declaration or Definition

static variable in the class declaration or definition?

The declaration in an implementation file outside of the header is required because otherwise every translation unit that includes this header would define its own object (that is, its own storage for the variable).

This would violate the One Definition Rule. A consequence would be e.g. that if the variable was changed in one translation unit, this change would be invisible to other translation units. Now, this isn’t that relevant since the variable is constant. However, taking its address would also yield different pointers in different translation units.

Why we declare static variable in a class & the definition in outside of the class?

I'm not sure but my guess is, because inside a class member variables are only declared. They are initialized through a constructor or other member functions.

This happens when an object is instantiated. However for static members, the objects need not be instantiated. Hence they need to be initialized once outside of the class.

EDIT:
Actually it is not necessary to initialize the static variables, but it is necessary to define them outside the class to allocate memory for them. Only after their definition, can they be initialized and then used in the program.

Why do we need to define static variables of a class, but we don't define static variables when they are inside functions?

The static member variable instance declared inside class Singleton in Code 1 is a class variable.

This means that regardless of the state of different instances of class Singleton, the state of static variable will remain the same for all objects/instances of that particular class. Hence, it needs to be defined outside the class.
(Just like a global variable which is available to function of all scopes.). A single copy of static member variable is allocated in memory even if you don't create any instance. Their definition persists through the entire file.

In Code 2, the static variable instance is not a class variable but is simply a local variable inside a static member function. Hence there is no need for it to be defined outside since its scope is limited only to static Singleton &GetInstance() function.

Where should static variables be declared

You declare the variables inside the class definition, then you define them in a source file.

But you need to use the proper scope when defining the variable, just like you use for member functions:

const int File::number = 10;
// ^^^^^^
// Note scope here

Why static variable needs to be explicitly defined?

From the beginning of time C++ language, just like C, was built on the principle of independent translation. Each translation unit is compiled by the compiler proper independently, without any knowledge of other translation units. The whole program only comes together later, at linking stage. Linking stage is the earliest stage at which the entire program is seen by linker (it is seen as collection of object files prepared by the compiler proper).

In order to support this principle of independent translation, each entity with external linkage has to be defined in one translation unit, and in only one translation unit. The user is responsible for distributing such entities between different translation units. It is considered a part of user intent, i.e. the user is supposed to decide which translation unit (and object file) will contain each definition.

The same applies to static members of the class. Static members of the class are entities with external linkage. The compiler expects you to define that entity in some translation unit. The whole purpose of this feature is to give you the opportunity to choose that translation unit. The compiler cannot choose it for you. It is, again, a part of your intent, something you have to tell the compiler.

This is no longer as critical as it used to be a while ago, since the language is now designed to deal with (and eliminate) large amount of identical definitions (templates, inline functions, etc.), but the One Definition Rule is still rooted in the principle of independent translation.

In addition to the above, in C++ language the point at which you define your variable will determine the order of its initialization with regard to other variables defined in the same translation unit. This is also a part of user intent, i.e. something the compiler cannot decide without your help.


Starting from C++17 you can declare your static members as inline. This eliminates the need for a separate definition. By declaring them in that fashion you effectively tell compiler that you don't care where this member is physically defined and, consequently, don't care about its initialization order.

Why do non-constant static variables need to be initialized outside the class?

Essentially it's because x exists independently of the number of instances of A that are created.

So storage for x needs to be defined somewhere - you can't rely on an instance of A to do that, and that's what

A::x = 0;

in exactly one translation unit, does.

Why C++ static data members are needed to define but non-static data members do not?

When you declare something, you're telling the compiler that the name being declared exists and what kind of name it is (type, variable, function, etc.) The definition could be with the declaration (as with your class A) or be elsewhere—the compiler and linker will have to connect the two later.

The key point of a variable or function definition is that it tells the compiler and linker where this variable/function will live. If you have a variable, there needs to be a place in memory for it. If you have a function, there needs to be a place in the binary containing the function's instructions.

For non-static data members, the declaration is also the definition. That is, you're giving them a place to live¹. This place is within each instance of the class. Every time you make a new A object, it comes with an ns as part of it.

Static data members, on the other hand, have no associated object. Without a definition, you've got a situation where you have N instances of A all sharing the same s, but nowhere to put s. Therefore, C++ makes you choose one translation unit for it via a definition, most often the source file that acommpanies that header.

You could argue that the compiler should just pick one instance for it, but this won't work for various reasons, one being that you can use static data members before ever creating an instance, after the last instance is gone, or without having instances at all.

Now you might wonder why the compiler and linker still can't just figure it out on their own, and... that's actually pretty much what happens if you slap an inline on the variable or function. You can end up with multiple definitions, but only one will be chosen.


1: Giving them a place to live is a little beside the point here. All the compiler needs to know when it creates an object of that class is how much space to give it and which parts of that space are which data members. You could think of it as the compiler doing the definition part for you since there's only one place that data member could possibly live.

static variables declared in a class whose type is same as that of the class

Because:

static A b;

(in the class itself) is not a definition, so the complete
definition of the class isn't necessary.

Java has different rules, and doesn't have the concept of an
incomplete type. And of course, variables in Java are never
user defined object types, but references (more like C++
pointers) to object types. The equivalent in C++ to your variable
declaration in Java would be Main* g;.



Related Topics



Leave a reply



Submit