views:

95

answers:

4

Hi,

I have in my header "Test.h" a variable of a class that doesn't have a constructor without arguments. And I have a constructor like this:

Test::Test() // <-- Here he complains:
             // error: no matching function for call to ‘Beer::Beer()’
{
   int i = 2;
   theVar = Beer(1, i); // Beer(int, int) is the only constructor
}

But I'm initializing it after the (empty) initializer list, in the constructor body.

How can I solve this? How is this problem called, if it has a name?

Thanks

+13  A: 

You need to use initializer list.

Test::Test() : theVar(1, 2) {}

If the problem is that i is the result of some other function call, you can do sometihng like

Test::Test() : theVar(1, compute_i()) {}

The problem is that the constructor body is executed after all members are initialized.

They are initialized first by calling whichever constructors are specified in the initializer list, and if the member is not listed there, by calling its default constructor.

That is why you get the error complaining about Beer::Beer(): because nothing else is specified, it tries to call that constructor to initialize theVar, and it doesn't exist.

Then after all members are initialized, the constructor body is executed (where you perform an assignment, and not an initialization, of theVar. But the compiler never gets that far, because it couldn't perform the initialization.

jalf
@jalf: Thank you very much for the explanation.
Martijn Courteaux
+3  A: 

You have to use the initializer list for every member variable that has a parameterized constructor:

Test::Test() :
   theVar( 1, 2 )
{
}

if you need the parameters to be computable in runtime - use static member functions for that and insert calls to them into the initializer list.

sharptooth
+1  A: 

You need to supply a default c'tor because the compiler will perform default-initialization on all class members before the c'tor runs. This cannot be avoided. You can, however, use a c'tor initializer list to specify a custom c'tor (I assume you know that).

A potential workaround would be to add such a private default c'tor to Beer and make Test a friend of Beer to prevent others from calling it accidentially.

This is, however, a design flaw. The best way is to redesign Base that it has a meaningful default c'tor, or redesign Test that you can initialize Base in the c'tor initializer list.

Alexander Gessler
+1  A: 

Write like this:

Test::Test() 
    : theVar(1, 2)
{ } 

otherwise the compiler tries to initialize Beer with a default constructor before it enters the constructor body. You must initialize member variables before entering the constructor body.

You may also consider having a default constructor, and set the members of Beer inside the constructor body.

Alexandre C.