Question

I'm reading this C++ open source code and I came to a constructor but I don't get it ( basically because I don't know C++ :P )

I understand C and Java very well.

 TransparentObject::TransparentObject( int w, int x, int y, int z ) : 
     _someMethod( 0 ),
     _someOtherMethod( 0 ),
     _someOtherOtherMethod( 0 ),
     _someMethodX( 0 ) 
  {
       int bla;
       int bla;
  }

As far I can "deduce" The first line only declares the construtor name, the "::" sounds like "belongs to" to me. And the code between {} is the constructor body it self.

I "think" what's after the paremeters and the first "{" are like methods default parameters or something, but I don't find a reasonable explanation on the web. Most of the C++ constructors that I found in the examples are almost identical to those in Java.

I'm I right in my assumptions? "::" is like belongs to, and the list after params and body are like "default args" or something?

UPDATE: Thanks for the answers. May those be called methods? ( I guess no ) and what is the difference of call them within the constructor body

Was it helpful?

Solution

The most common case is this:

class foo{
private:
    int x;
    int y;
public:
    foo(int _x, int _y) : x(_x), y(_y) {}
}

This will set x and y to the values that are given in _x and _y in the constructor parameters. This is often the best way to construct any objects that are declared as data members.

It is also possible that you were looking at constructor chaining:

class foo : public bar{
    foo(int x, int y) : bar(x, y) {}
};

In this instance, the class's constructor will call the constructor of its base class and pass the values x and y.

To dissect the function even further:

TransparentObject::TransparentObject( int w, int x, int y, int z ) : 
   _someMethod( 0 ),
   _someOtherMethod( 0 ),
   _someOtherOtherMethod( 0 ),
   _someMethodX( 0 ) 
{
     int bla;
     int bla;
}

The ::-operator is called the scope resolution operator. It basically just indicates that TransparentObject is a member of TransparentObject. Secondly, you are correct in assuming that the body of the constructor occurs in the curly braces.

UPDATE: Thanks for the answers. May those be called methods? ( I guess no ) and what is the difference of call them within the constructor body

There is much more information on this subject than I could possibly ever give you here. The most common area where you have to use initializer lists is when you're initializing a reference or a const as these variables must be given a value immediately upon creation.

OTHER TIPS

You are pretty close. The first line is the declaration. The label left of the :: is the class name and for it to be a constructor, the function name has to be the same as the class name.

TransparentObject::TransparentObject( int w, int x, int y, int z )

In C++ you can optionally put a colon and some initial values for member variables before the start of the function body. This technique must be used if you are initialzing any const variables or passing parameters to a superclass constructor.

: 
 _someMethod( 0 ),
 _someOtherMethod( 0 ),
 _someOtherOtherMethod( 0 ),
 _someMethodX( 0 )

And then comes the body of the constructor in curly braces.

{
   int bla;
   int bla;
}

:: Actually means contains (see comments for clarification), however the _someMethods and so forth is what's called an initialisation list. There is plenty of info at the link =]

EDIT: Sorry, my first sentence is incorrect - see the comments.

Yes, :: is the C++ scoping operator which lets you tell the compiler what the function belongs to. Using a : after the constructor declaration starts what is called an initialization list.

The code between the argument list and the {}s specifies the initialization of (some of) the class members.

Initialization as opposed to assignment---they are different things---so these are all calls to constructors.

You're correct. Its a way to set the default values for the class variables. I'm not too familiar with the exact difference between putting them after : and in the function body.

There are usually some good reasons to use an initialization list. For one, you cannot set member variables that are references outside of the initialization list of the constructor. Also if a member variable needs certain arguments to its own constructor, you have to pass them in here. Compare this:

class A
{
public:
  A();
private:
  B _b;
  C& _c;
};

A::A( C& someC )
{
  _c = someC; // this is illegal and won't compile. _c has to be initialized before we get inside the braces
  _b = B(NULL, 5, "hello"); // this is not illegal, but B might not have a default constructor or could have a very 
                            // expensive construction that shouldn't be done more than once
}

to this version:

A::A( C& someC )
: _b(NULL, 5, "hello") // ok, initializing _b by passing these arguments to its constructor
, _c( someC ) // this reference to some instance of C is correctly initialized now
{}

Without using the initialiser list all class members will simply have their default constructor called so this is the only place that you can control which constructor is called (for non-dynamically allocated members). The same is true for which parent class constructor will be called.

Class members "initialised" within the body of the constructor (i.e. between the {} braces using the = operator) isn't technically initialisation, it's an assignment. For classes with a non-trivial constructor/destructor it can be costly to default construct and then modify through assignment in this way. For reference members you must use the initialiser list since they cannot be changed via the assignment operator.

If the member (or parent class) does not have a default constructor then failing to specify an appropriate constructor in the initialiser list will cause the compiler to generate an error. Otherwise the compiler will insert the default constructor calls itself. For built in types this does nothing so you will have garbage values there.

Note that the order in which you specify the members in the initialiser list does not affect the order in which they are called. It is always the parent class constructor (if any) first, then the class members in the order in which they are defined in the class definition. The order in which you put them in the initialiser list does not matter and can be the source of subtle bugs...

In the contrived example below it looks like the intention is to initialise m_b with value then m_a with m_b, but what actually happens is that m_a is initialised with m_b (which is itself not yet initialised) then m_b gets initialised with value. m_b will just contain garbage!

struct BadInitialiserListExample
{
    BadInitialiserListExample(int value) :
        m_b(value),
        m_a(m_b)      // <-- *BUG* this is actually executed first due to ordering below!
    {
    }

    int    m_a;
    int    m_b;
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top