开发者

why do " int ClassName :: VariableName " always needed to complete linkage?

开发者 https://www.devze.com 2023-02-09 13:24 出处:网络
class X { static int i; // some other function, variable declaration, cons, dest 开发者_StackOverflow};
  class X {
       static int i;
       // some other function, variable declaration, cons, dest
开发者_StackOverflow  };

  int X :: i ; **(!)** 

Why must I write that (!) line, always ?

If I dont write, compiler cannot complete internal linkage, and so it gives ( I assume ) linker error. Why ?


This is known as the One Definition Rule. Each global object (technically, each object with external linkage) must be defined in exactly one source file (technically, in one translation unit). However, it can be declared as many times as you like.

Typically, a class definition will be in a header file, which might be included by many source files. So any static members can't be defined there, only declared, otherwise there will be multiple definitions. You must separately define the static members in exactly one source file, in order for the linker to find exactly one definition. That is what the line marked (!) does.


Because that is how static members work. They exist apart from the instances directly in the class.

You can't define them inside the class, because then you would have multiple definitions for every implementation file that is using your class.

Therefore you need to choose one implementation file that will actually define the static member.


The static variable must be defined (as opposed to declared) in a TU (i.e. a cpp file).

If it's only declared and not defined, no storage is allocated for it, so the linker can't find it.


static int i; is a declaration, i.e. tells to the compiler that in some translation unit (=>.cpp file) such static field will be actually defined. It is needed to let the compiler know that such variable exists and to let you use it in each translation unit where it's declared.

int X :: i;, instead, is a definition, it tells to the compiler to actually provide the space for that variable. It must stay in a single .cpp, otherwise each translation unit would provide some space for it on its own (and the linker would complain).

It's the exact same reason why for globals you need an extern declaration in every file that needs to use it (usually put in a header) and a normal definition in the single .cpp that defines it.


C++ makes a clear distinction between declaration and definition. You need to tell the compiler two things:

  1. The data type of the variable: declaration.
  2. The place in memory on where you want your variable to be located: definition.

This is usually done in one single step, ie a local int variable:

void f() {
    int x; // Declaration and definition.
}

Since a .hpp header file can be included on many .cpp files, your (!) line must reside on a single specific .cpp, usually outside any header file.


Static class members are shared among all class instances (there is one and only place in memory where such variable resides) and therefore static int i; inside class declaration represents variable declaration only - and you need to allocate memory for that variable somewhere - you need to define it - which is done in implementation file with int X::i;


The class definition only defines the member, but it must exist in a single compilation unit (i.e. a .cpp file).

You could say it is part of the "one-definition rule".

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号