12

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.

Vishnu CS
  • 748
  • 1
  • 10
  • 24
Jeremy Salwen
  • 8,061
  • 5
  • 50
  • 73
  • I realize this is an example, and not actual code, but just for the sake of ~~being a pedant~~ code quality, it's generally not a good idea to make fields `public`. Sure, there are some use cases, and it's not _universally_ bad, but before doing it, make sure there's a reason beyond "it might simplify some of my code" ("it does simplify a lot of my code" is a perfectly acceptable reason, though) – Nic Mar 06 '17 at 19:36

5 Answers5

24

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.

i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
  • Thanks a lot. I thought that was only for calling parent class constructors. – Jeremy Salwen Jan 18 '10 at 20:31
  • 2
    Yep, you can also use it to initialize members. – i_am_jorf Jan 18 '10 at 20:53
  • In some cases, you have to initialize members (references, for example), and this is how you do it. – David Thornley Jan 18 '10 at 21:07
  • 1
    Bear in mind that members are initialized in the order of their declaration in the class, not in the initializer list. – Mike DeSimone Jan 18 '10 at 21:16
  • @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. – i_am_jorf Jan 18 '10 at 21:19
3

Use an initialization list:

b::b() : aInstance(1) {}
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
0

Just use a constructor which is defined like this:

class b {
public:
    b()
    : aInstance(5)
    {}
    a aInstance;
};
i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
Dmitry
  • 6,590
  • 2
  • 26
  • 19
0

The top two answers won't work. You put class declarations in the .h header files, and (member) function definitions in the .cpp files. The braces {} that the respondents have put define the b constructor block. In practice no one would want that empty. Yet you can't define it properly in the .cpp or the compiler will report error of 'redefinition'. (As the linker would anyway if the header file is #included in several translation units) Since the purpose of header files is that they CAN be included in several .cpp's the answers above are unfeasable.

Clive
  • 269
  • 1
  • 14
-2

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
  • 9,789
  • 2
  • 36
  • 53
  • 1
    Heap allocation is very much not preferred to stack allocation. Your code is now missing a copy-constructor, assignment operator, and destructor. – GManNickG Jan 18 '10 at 21:23
  • 1
    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 Jan 18 '10 at 22:09