6

I've been solving hackerrank questions. I've encountered with a virtual function question and I've been asked to create a class named Student . This class must have a int variable named cur_id ( current id). Here is the class;

class Student: public Person{

    public:

    static int id;

    Student(){
        cur_id = ++id;
    }


};

int Student::id = 0;

I've been asked to increase the cur_id +1 while every new object of the class is being created. So that, i decided to increase the cur_id in the constructor. As you can see, I've declared a static int variable in the class as static int id. Then I wanted to initialize its value with zero out of the class. But when I tried it as Student::id = 0;, I couldn't access the id variable. I needed to specify its datatype one more time like I am declaring the variable again as int Student::id = 0;. What's the reason of it, why do I need to declare a static variable two time ? I know that it's a newbie question and may have an easy answer, but I couldn't find my answer in another topics. Thanks in advance.

Ozan Yurtsever
  • 1,274
  • 8
  • 32
  • 1
    There's [this question](https://stackoverflow.com/questions/36697711), that seems relevant. – StoryTeller - Unslander Monica Dec 10 '18 at 09:52
  • You should also clarify what sort of "why" you are asking about. Is it about rationale or about pointing out the specific part of the language specification that requires it? – StoryTeller - Unslander Monica Dec 10 '18 at 09:53
  • @StoryTeller, I want to learn the language spesification that requires it. Why do we need to declare it 2 times . – Ozan Yurtsever Dec 10 '18 at 09:54
  • static data members must be explicitly defined in exactly one compilation unit. If you wont define you will get eror "Undefined reference" isn't a compiler error; it's a linker error. It means that a definition of A::x can't be found in any of the translation units that are being linked together to form your program. Static member variables have external linkage and must be defined in exactly one translation unit. Anything with external linkage will not have a definition generated by the compiler unless you write one. – ban Dec 10 '18 at 09:56
  • C++17 lets you initialize a static member variable inside a class (inside a header file) if you make it `inline`. – Daniel Langr Dec 10 '18 at 10:00
  • @ban, but why a static variable MUST be explicitly defined in a compilation unit ? What does make it different than a normal local data type. – Ozan Yurtsever Dec 10 '18 at 10:08
  • 1
    @OzanYurtsever this is a different question. Either [edit] your question to improve it or ask another question. – YSC Dec 10 '18 at 10:17
  • @OzanYurtsever Because you can link your program from multiple compilation units, and C++ requires all symbols with external linkage to be defined just in one of them. An exception are _inline_ functions/variables. – Daniel Langr Dec 10 '18 at 10:18
  • 1
    @OzanYurtsever, look at here https://stackoverflow.com/questions/29223949/why-static-variable-needs-to-be-explicitly-defined – ban Dec 10 '18 at 10:34
  • 100% opinion based: repetition are there for reassure coders. that gives the feeling of control we have when we code in assembly (even if this feeling is such a lie!) – Oliv Dec 10 '18 at 16:50

1 Answers1

8

The second time you do not declare it. You define it. This is why this is typically done in an implementation file (.cpp) while the class declaration is done in a header file (.h).

Benjamin Bihler
  • 1,612
  • 11
  • 32
  • 1
    Good answer. minor nitpick: every definition is a declaration ;) `::Student::id` id declared twice, defined once. – YSC Dec 10 '18 at 09:53
  • But why we specified the int type again when we define it in the second time ? – Ozan Yurtsever Dec 10 '18 at 10:06
  • @OzanYurtsever so your question is : _why do we need to write `int Student::id = 0;` instead of `Student::id = 0;`?_ Please confirm. – Jabberwocky Dec 10 '18 at 10:15
  • @Jabberwocky, yes. – Ozan Yurtsever Dec 10 '18 at 10:15
  • With that you exactly specify what you are going to define. – Benjamin Bihler Dec 10 '18 at 10:16
  • @OzanYurtsever when you write the implementation of a _method_, you also repeat the return type: e.g: `class Foo {int bar();};`and then you need to write `int Foo::bar() {...}` instead of `Foo::bar() {...}`. That's simply a rule of the C++ language – Jabberwocky Dec 10 '18 at 10:17
  • @Jabberwocky, nice example. But why we behave to static like a function, not like a standart variable ? Or let's inverse the question, why don't we specify the data types again for normal variables in the implementation ? – Ozan Yurtsever Dec 10 '18 at 10:22
  • @OzanYurtsever _"why don't we specify the data types again for normal variables in the implementation"_: what do you mean?? Please show an example. – Jabberwocky Dec 10 '18 at 10:23
  • @Jabberwocky, for example we've declared a variable in our header file as `int var`. Then when we want to initialize it with a value, we just need to use it as ` var = 5` in the cpp file. There is no need to specify its data type `int` one more time. – Ozan Yurtsever Dec 10 '18 at 10:31
  • 1
    @OzanYurtsever If you _declare_ a "normal" global variable (e.g. `extern int i;` in a header file), then you need it to define this variable in a single compilation unit (typically in a single source file, e.g., `int i = 0;`). Both declaration and definition require to write the variable's type. – Daniel Langr Dec 10 '18 at 10:31
  • @DanielLangr, so you mean that this difference occurs because of the scope ? – Ozan Yurtsever Dec 10 '18 at 10:32
  • 1
    @OzanYurtsever That's not true. You cannot write `var=5;` outside of the function body. Inside a function body, this is not an _initialization_, this is as _assignment_. – Daniel Langr Dec 10 '18 at 10:33
  • 1
    @OzanYurtsever I don't see any difference. Please, show us what you mean. Edit your question to provide exemplary code. Both for header file and source file. And both for static member variable and "normal" variable. – Daniel Langr Dec 10 '18 at 10:35