0

I am currently working on a calculator program from chapter 6 in Principles and practice using C++ by Stroustrup, and I came across this statement which was not explained in the book and I could not find any reference online (more like I did not know what to search for).

Token(char ch)    // make a Token from a char
        :kind(ch), value(0) { }
Token(char ch, double val)     // make a Token from a char and a double
        :kind(ch), value(val) { }

I'd appreciate any explanation on this.

Here is the full block:

class Token {
public:
    char kind;        // what kind of token
    double value;     // for numbers: a value
    Token(char ch)    // make a Token from a char
        :kind(ch), value(0) { }
    Token(char ch, double val)     // make a Token from a char and a double
        :kind(ch), value(val) { }
};

Thanks in advance.

user207787
  • 119
  • 2

2 Answers2

3

They are called constructor member initializer lists.

Token(char ch)   
    :kind(ch), value(0) { } // the initialization list starts after the colon

They initialize their members before the constructor enters the function body. It is important to note that the initialization order is defined by the order of declaration in the class: since char kind is declared before int value, kind has to be initialized first in the list. Using another order in the initialization list is not recommended as this may cause confusion to future maintainers.

Martin York
  • 257,169
  • 86
  • 333
  • 562
Philipp
  • 2,376
  • 5
  • 29
  • 47
  • 3
    Order of the initializers is "important" only in the sense that a different order is misleading. The language allows any order, but the base classes and members are always initialized in declaration order, ignoring the order of the constructor's initialization list. So if any initializers have side effects or depend on another base or member of the same object already being initialized, writing in another order might make it look like the behavior is different than it actually will be. But sometimes, as with these fundamental member types, it really doesn't matter. – aschepler Jan 08 '19 at 23:09
  • 1
    Pretty sure [the rule is that `kind` *is* initialized first, not that it has to *appear* first](https://en.cppreference.com/w/cpp/language/initializer_list#Initialization_order). `:value(val), kind(ch)` would be equally legal, it would just behave the same as the `:kind(ch), value(val)` (matching the member declaration order). – ShadowRanger Jan 08 '19 at 23:09
0

As other users have already mentioned, these are constructor member initializer lists. They can be used to set specific values for data fields as well as provide default values. For example, the first constructor in the block of code you included initializes the kind field of the instance of Token to ch and initializes the value field to 0. Here is an example of this constructor being called:

char x = 'a';
Token t(x);

This line of code would create an instance of the Token class t with t.kind equal to 'a' and t.value equal to 0.

Why use them? You could write a conventional constructor that would accomplish the same thing, for example:

Token(char ch) {
    kind = ch;
    value = 0;
}

Token(char ch, double val) {
    kind = ch; 
    value = val;
}

Construction member initializer lists are just more concise ways to accomplish the exact same thing.

sadiela
  • 106
  • 7