Initializing composed objects

A

alacrite

If I have this situation

class X
{
Z z;
Y y;
};

Class X has two objects of type Z and Y. How do I initialize z and y
with non default constructors?

X::X()
{
z(1);
y(2);
}

If I do something like the previous I get the following error:

line 2, Error: Could not find Z::Z() to initialize z.
line 2, Error: Could not find Y::Y() to initialize y.
line 3, Error: Only a function may be called.
line 3, Error: Only a function may be called.
 
V

Victor Bazarov

If I have this situation

class X
{
Z z;
Y y;
};

Class X has two objects of type Z and Y. How do I initialize z and y
with non default constructors?

Use the constructor _initializer_list_ (look it up).
X::X()
{
z(1);
y(2);
}

If I do something like the previous I get the following error:

line 2, Error: Could not find Z::Z() to initialize z.
line 2, Error: Could not find Y::Y() to initialize y.
line 3, Error: Only a function may be called.
line 3, Error: Only a function may be called.

V
 
S

Salt_Peter

If I have this situation

class X
{
Z z;
Y y;
};

Class X has two objects of type Z and Y. How do I initialize z and y
with non default constructors?

X::X()
{
z(1);
y(2);
}

The exact same way you would initialize Z if it had a member.

class Z
{
int z;
public:
Z() : z(0) { } // def ctor
Z(int n) : z(n) { } // parametized ctor
};

int main()
{
Z instance_0; // instance_0.z == 0
Z instance_1(1); // instance_1.z == 1
}
 
A

alacrite

Salt_Peter said:
The exact same way you would initialize Z if it had a member.

class Z
{
int z;
public:
Z() : z(0) { } // def ctor
Z(int n) : z(n) { } // parametized ctor
};

int main()
{
Z instance_0; // instance_0.z == 0
Z instance_1(1); // instance_1.z == 1
}

The goal of what I am trying to do is to give some variables of type Z
and Y scope of class X but delay there initalization until all other
dependencies have been met. For example the Constructor of X may have
to go to the database before it can populate Z and Y with thier values.
So in that case I don't think constructor initalizer list technique
would be able to be used in that case.
 
V

Victor Bazarov

Salt_Peter said:
If I have this situation

class X
{
Z z;
Y y;
};

Class X has two objects of type Z and Y. How do I initialize z and y
with non default constructors?

X::X()
{
z(1);
y(2);
}
[...]

The goal of what I am trying to do is to give some variables of type Z
and Y scope of class X but delay there initalization until all other
dependencies have been met. For example the Constructor of X may have
to go to the database before it can populate Z and Y with thier
values. So in that case I don't think constructor initalizer list
technique would be able to be used in that case.

You cannot *initialise* them that way. You can only hope to *assign*
them at best, if you have to do

X::X()
{
/* some complicated processing */
z = Z(somevalue_from_processing);
y = Y(someothervalue);
}

Now, since your 'Z' and 'Y' don't seem to have default constructors,
you _have_ to provide some values to *initialise* the members with.
So, it gets ugly relatively quickly:

X::X() : z(dummy_value_for_z), y(dummy_value_for_y)
{
/* some complicated processing */
z = Z(somevalue_from_processing);
y = Y(someothervalue);
}

Perhaps you can re-design your initialisation procedure...

V
 
S

Salt_Peter

The goal of what I am trying to do is to give some variables of type Z
and Y scope of class X but delay there initalization until all other
dependencies have been met. For example the Constructor of X may have
to go to the database before it can populate Z and Y with thier values.
So in that case I don't think constructor initalizer list technique
would be able to be used in that case.

And why not? Whats preventing from initializing a variable to a valid
state and then reset the variable with a some dependancy when
available? Likewise, whats preventing you from completing some
dependancy and still intialize the variables in that init list?

Remember job #1, always , always initialize all your members. Even if
you will never use them. Take as an example a pointer. If you set that
pointer to 0 in the init list and happen to use it without
initialization it by accident - the result and the solution will be
obvious. If that pointer isn't initialized at all, you'll dig high and
low for the bug for a week. The same applies for any member.

Why take away the support a compiler can give you?
Interestingly enough, take a look at what happens if you do have a
dependancy:

#include <iostream>

class Z
{
char m_char;
public:
Z() : m_char( getInput() ) { std::cout << "Z()\n"; } // def ctor
~Z() { std::cout << "~Z()\n"; }
/* member functions */
char getInput() const
{
std::cout << "enter a char between b and e (default: a): ";
char c;
std::cin >> c;
if( (c >= 'b' && c <= 'e' ) && std::cin.good() )
{
return c;
} else {
return 'a';
}
}
const char& get() const { return m_char; }
};

int main()
{
Z instance;
std::cout << "instance.m_char = ";
std::cout << instance.get() << std::endl;
return 0;
}

/* sample output
enter a character between b and e (default: a): c
Z()
instance.m_char = c
~Z()
*/

Try a primitive array of Zs.
 
A

alacrite

Salt_Peter said:
And why not? Whats preventing from initializing a variable to a valid
state and then reset the variable with a some dependancy when
available? Likewise, whats preventing you from completing some
dependancy and still intialize the variables in that init list?

Remember job #1, always , always initialize all your members. Even if
you will never use them. Take as an example a pointer. If you set that
pointer to 0 in the init list and happen to use it without
initialization it by accident - the result and the solution will be
obvious. If that pointer isn't initialized at all, you'll dig high and
low for the bug for a week. The same applies for any member.

Why take away the support a compiler can give you?
Interestingly enough, take a look at what happens if you do have a
dependancy:

#include <iostream>

class Z
{
char m_char;
public:
Z() : m_char( getInput() ) { std::cout << "Z()\n"; } // def ctor
~Z() { std::cout << "~Z()\n"; }
/* member functions */
char getInput() const
{
std::cout << "enter a char between b and e (default: a): ";
char c;
std::cin >> c;
if( (c >= 'b' && c <= 'e' ) && std::cin.good() )
{
return c;
} else {
return 'a';
}
}
const char& get() const { return m_char; }
};

int main()
{
Z instance;
std::cout << "instance.m_char = ";
std::cout << instance.get() << std::endl;
return 0;
}

/* sample output
enter a character between b and e (default: a): c
Z()
instance.m_char = c
~Z()
*/

Try a primitive array of Zs.

Ok, After the last two responses I understand the situation much
better. So thank you Victor Bazarov and Salt_Peter for the help.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top