Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>Short answer</h2> <p>That is a constructor with an empty body, and a <em>member initialisation list</em> that initialises two data members to the value <code>0</code>.</p> <p>i.e.</p> <ul> <li><p><code>class-name([ ctor-args ]) [ : member-init-list ] { [ ctor-body ] }</code></p></li> <li><p>where <code>member-init-list</code> is <code>member-name(args) [, member-name(args) [, ... ] ]</code>.</p></li> </ul> <p><sup>(Note: not actual C++ lexical grammar constructions)</sup></p> <hr> <h2>Long answer</h2> <h3>Background</h3> <p>Take the following class definitions:</p> <pre><code>struct Base {}; struct Derived : Base {}; </code></pre> <p>You may already be aware that <code>Derived</code> derives from <code>Base</code>.</p> <p>You may also already be aware that <code>Derived</code> and <code>Base</code> both have a <em>synthesised</em> (implicitly-declared) default (takes no arguments) constructor. <code>Derived</code>'s constructor implicitly/automatically invokes <code>Base</code>'s.</p> <p>Now let's add a basic member function:</p> <pre><code>struct Derived : Base { void foo() {} }; </code></pre> <p>I have both declared <em>and</em> defined this member function <code>foo</code>; its body is empty, so nothing happens when you invoke it. This is pretty pointless, but it's perfectly valid.</p> <p>Now, instead, let's make our own constructor:</p> <pre><code>struct Derived : Base { Derived() {} }; </code></pre> <p>This looks more familiar. It's still a [special] function with an empty body, and the <code>Base</code> constructor is still being implicitly invoked. We haven't changed that.</p> <hr> <h3>Handling data members</h3> <p>Let's add some data members and set their value in our constructor:</p> <pre><code>struct Derived : Base { Derived() { x = 0; y = 0; } int x, y; }; </code></pre> <p>Both <code>x</code> and <code>y</code> will have the value <code>0</code> after object construction. This is still fundamental C++.</p> <p>But what you may <em>not</em> be aware of is that you are not <em>initialising</em> these data members. You are merely assigning to them <em>after</em> the possibility of initialising them.</p> <p>In fact, data members of built-in types are not implicitly initialised, so let's pick a better example:</p> <pre><code>struct Derived : Base { Derived() /* HERE */ { x = ""; y = ""; } std::string x, y; }; </code></pre> <p><code>x</code> and <code>y</code> are implicitly initialised <em>before</em> the code in the constructor body runs. When the constructor body starts to run, <em>all members that will be initialised, have already been initialised</em>, and the base constructor has been implicitly invoked.</p> <p>We can intercept this behaviour and provide our <em>own</em> initialisation values by writing a <strong>member initialiser list</strong> in the place where I wrote <code>/* HERE */</code> in the previous snippet. With the member initialiser list, the snippet looks like this:</p> <pre><code>struct Derived : Base { Derived() : x(""), y("") { x = ""; y = ""; } std::string x, y; }; </code></pre> <p>Wow! OK; now we're initialising the strings to <code>""</code>, <em>and</em> later assigning the same, empty value to them in the constructor body. We can get rid of those assignments, then:</p> <pre><code>struct Derived : Base { Derived() : x(""), y("") {} std::string x, y; }; </code></pre> <p>Now the constructor body is empty, but the constructor still does stuff. It implicitly invokes the base constructor, and it <em>explicitly</em> initialises the data members <code>x</code> and <code>y</code> to the empty string.</p> <p>And, because <code>std::string</code> has a default constructor that does the same, we can write for short:</p> <pre><code>struct Derived : Base { Derived() : x(), y() {} std::string x, y; }; </code></pre> <p>Going back to your original example, this applies to objects of built-in types just as easily. Let's consider two pointers:</p> <pre><code>struct Derived : Base { Derived() : next(0), prev(0) {} Derived* next; Derived* prev; }; </code></pre> <hr> <h3>Handling base classes</h3> <p>And, as an added bonus, we can use the member initialisation list to invoke the base constructor <em>explicitly</em>:</p> <pre><code>struct Derived : Base { Derived() : Base(), next(0), prev(0) {} Derived* next; Derived* prev; }; </code></pre> <p>This is pretty pointless unless the base constructor wants some arguments:</p> <pre><code>struct Base { Base(int x) {} }; struct Derived : Base { Derived() : Base(0), next(0), prev(0) {} Derived* next; Derived* prev; }; </code></pre> <hr> <p>I hope that this has been useful.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload