unusual function definition

Jun 17, 2013 at 8:57pm
I ran into the following definition of a function that looked rather unusual to me. Can somebody explain the rules of the definition or/and provide a link where it would be explained.
1
2
3
4
5
6
7
8
class A{
   public:
      A(int n=0);
   protected:
      int m_n;
};

A::A(int n) : m_n(n){ };


The last line that defines the constructor A(n) seams to be equivalent to
 
A::A(int n){m_n=n; };

Is there any difference between the two lines in this or other circumstances?
What is the logic/origin of the first definition?

Thank you!
Jun 17, 2013 at 9:00pm
It is called an initializer list. It works as if you declared the variable and initialized it on the same line.
1
2
int n;
int m = n;


Your version is assigning, which happens after the variable is created:
1
2
3
int n;
int m;
m = n;


When you have const member variables or member objects whose class has no default constructor, this difference become important.
Jun 17, 2013 at 9:28pm
Daleth,
although there are several differences between the two versions of the code above, the most unusual to me is the implementation of the function outside the parenthesis
: ... {}
versus
{...}

Can you comment on that?
Jun 17, 2013 at 9:42pm
1
2
3
Foo::Foo(int n) //end of argument list
   : m(n) //initializer list; denoted by the colon
{}
Jun 17, 2013 at 10:37pm
Daleth,
thanks a lot. I think I understand it in part.

First, here is a part I understand best illustrated by the following example.
In the following code the constructor of B will be called twice, first the default one then the one with an integer parameter.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

using namespace std;

class B{
   public:
      B(){
         cout << "B's empty constructor\n";
      };

      B(int k){
         cout << "B's constructor with k=" << k << endl;
         n = k;
      };

      int n;
};

class A {
   public:
      A(int k);

      B b;
};

A::A(int k){b = *new B(k);}

int main(){
   A a(3);
}

On the other hand, if I define the constructor A(int ) using initialization list as follows
 
A::A(int k) : b(k){};

I can eliminate the call to the default constructor B().

Here is the part I don't understand, yet.
Suppose the class A contained two or more objects that needed initialization, say B and C.
How can I use the initialization list to avoid using their default constructors?

Jun 17, 2013 at 10:58pm
b = *new B(k);
¡¿why do you use new there?!

> Suppose the class A contained two or more objects that needed initialization
1
2
3
4
5
6
7
8
A::A(int k):
   foo(42),
   bar(this),
   adsf(k),
   qwerty("hello world")
{
   //...
}
Jun 17, 2013 at 11:01pm
Same way you initialize them when you declare objects.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct A{
   A(int);
};
struct B{
   B(int);
};
struct C{
   C(int);
};

struct Foo{
   Foo(int,int,int);
   A a;
   B b;
   C c;
};

Foo::Foo(int I, int j, int k)
   : a(I), b(j), c(k)
{}


What kind of and how many parameters your constructor will take depends on the designs of your classes.
Topic archived. No new replies allowed.