views:

197

answers:

4

I have two classes

class a {
    public:
        a(int i);
};

class b {
    public:
        b(); //Gives me an error here, because it tries to find constructor a::a()
        a aInstance;
}

How can I get it so that aInstance is instantiated with a(int i) instead of trying to search for a default constructor? Basically, I want to control the calling of a's constructor from within b's constructor.

+13  A: 

You need to call a(int) explicitly in the constructor initializer list:

b() : aInstance(3) {} 

Where 3 is the initial value you'd like to use. Though it could be any int. See comments for important notes on order and other caveats.

jeffamaphone
Thanks a lot. I thought that was only for calling parent class constructors.
Jeremybub
Yep, you can also use it to initialize members.
jeffamaphone
In some cases, you have to initialize members (references, for example), and this is how you do it.
David Thornley
Bear in mind that members are initialized in the order of their declaration in the class, not in the initializer list.
Mike DeSimone
@Mike: yes, in gcc (mac, linus) and according to The Standard the initializer list must be in the same order the members are declared. The Microsoft compiler doesn't enforce (or warn) if you do it in a different order, but you shouldn't rely on that behavior. Additionally, using "this" is dangerous since your object isn't fully constructed yet. Some compilers will warn if you do this, some won't.
jeffamaphone
+4  A: 

Use an initialization list:

b::b() : aInstance(1) {}
Jerry Coffin
A: 

Just use a constructor which is defined like this:

class b {
public:
    b()
    : aInstance(5)
    {}
    a aInstance;
};
Dmitry
This is not valid C++.
Roger Pate
With a member variable, this will only work if the variable is a `static const`, as in `static const int x(3);`
Jerry Coffin
I actually should note that I am not passing a constant to the constructor, but another member of b. When I try to do a aInstance(c);it interprets that as a function definition.
Jeremybub
@Jerry: and has integral type.
Roger Pate
Sorry, my bad, what was I thinking of... fixing the example to use init list.
Dmitry
@Roger: yes, that too, now that you mention it. Thanks.
Jerry Coffin
A: 

I think you should use a pointer to 'a' like:

class b {
public:
    b() : aInstance(new a(5)) {}
    a *aInstance;
};

This way you will have defined behaviour. Of course you will need to free *aInstance in the destructor.

Maurits Rijk
Heap allocation is very much not preferred to stack allocation. Your code is now missing a copy-constructor, assignment operator, and destructor.
GMan
I agree. I was a bit too fast with my comment, especially since aInstance is just a small object. I was thinking about real-life situations where objects could be bigger, where you might have lazy initialization, etc. I guess I have been doing too much C# and Java lately where almost everything is done by reference ;)
Maurits Rijk