Discussion:
Is it a good way to use constructor?
(too old to reply)
Lorry Astra
2009-08-06 12:30:05 UTC
Permalink
Dear all,
I have a question in today's code review, here is my code example:
class A{
public:
A(B& b)
{....}
};

class B{
public:
B() : A(*this)
{....}
};

I think here exists a risk in class B constructor. Because I think when
constructor A is executed before constructon B ("B() : A(*this)"),
constructor A uses an object of class B as parameter. But I believe the
object of class B is not generated while constructor A running. So I think
"A(*this)" is a risk.
So I think if this code is like that, the executed sequence will be:
1. A(*this) -> A(B& b)
2. B()

Is that right? Are there any errors in my description?
Thanks.

Br,

Lorry
Victor Bazarov
2009-08-06 13:06:05 UTC
Permalink
Post by Lorry Astra
Dear all,
class A{
A(B& b)
'B' hasn't been defined or declared at this point.
Post by Lorry Astra
{....}
};
class B{
B() : A(*this)
This is ill-formed unless 'B' derives from 'A'.
Post by Lorry Astra
{....}
};
I think here exists a risk in class B constructor.
A risk of what?
Post by Lorry Astra
Because I think when
constructor A is executed before constructon B ("B() : A(*this)"),
constructor A uses an object of class B as parameter.
So?
Post by Lorry Astra
But I believe the
object of class B is not generated while constructor A running.
You mean it hasn't been completely constructed yet, yes?
Post by Lorry Astra
So I think
"A(*this)" is a risk.
A risk of *what*?
Post by Lorry Astra
1. A(*this) -> A(B& b)
2. B()
Is that right? Are there any errors in my description?
Yes, plenty. First off, the code is ill-formed. Please fix the code
and ask your question again then. In the mean time read the C++ FAQ,
section 10, question 10.7.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Lorry Astra
2009-08-06 13:42:08 UTC
Permalink
Sorry, I make a mistake here, I rewrite them.
class A{
public:
A(B& b){}
};

class B{
A a;
public:
B() : a(*this)
{}
};

It should be an composition, not a inheritance, sorry about that. But I
have the same question, I think when object a is constructed using "*this", I
believe "*this" is not existed at that time. Is that right? Because
constructor B is not executed while a(*this) running.
Post by Victor Bazarov
Post by Lorry Astra
Dear all,
class A{
A(B& b)
'B' hasn't been defined or declared at this point.
Post by Lorry Astra
{....}
};
class B{
B() : A(*this)
This is ill-formed unless 'B' derives from 'A'.
Post by Lorry Astra
{....}
};
I think here exists a risk in class B constructor.
A risk of what?
Post by Lorry Astra
Because I think when
constructor A is executed before constructon B ("B() : A(*this)"),
constructor A uses an object of class B as parameter.
So?
Post by Lorry Astra
But I believe the
object of class B is not generated while constructor A running.
You mean it hasn't been completely constructed yet, yes?
Post by Lorry Astra
So I think
"A(*this)" is a risk.
A risk of *what*?
Post by Lorry Astra
1. A(*this) -> A(B& b)
2. B()
Is that right? Are there any errors in my description?
Yes, plenty. First off, the code is ill-formed. Please fix the code
and ask your question again then. In the mean time read the C++ FAQ,
section 10, question 10.7.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Scot T Brennecke
2009-08-07 06:27:39 UTC
Permalink
Ah, composition, not inheritance. Big difference. It changes the answer entirely.
During the class initializer of B(), the B object is not fully constructed, but 'this' does exist. It points to the B object that
is in the middle of being constructed. If A(B&) does not attempt to use the B object in its constructor, it should be safe to keep
a reference to it for later. If B has any base classes, their constructors will have been completed by the time A() is called.
Post by Lorry Astra
Sorry, I make a mistake here, I rewrite them.
class A{
A(B& b){}
};
class B{
A a;
B() : a(*this)
{}
};
It should be an composition, not a inheritance, sorry about that. But I
have the same question, I think when object a is constructed using "*this", I
believe "*this" is not existed at that time. Is that right? Because
constructor B is not executed while a(*this) running.
Post by Victor Bazarov
Post by Lorry Astra
Dear all,
class A{
A(B& b)
'B' hasn't been defined or declared at this point.
Post by Lorry Astra
{....}
};
class B{
B() : A(*this)
This is ill-formed unless 'B' derives from 'A'.
Post by Lorry Astra
{....}
};
I think here exists a risk in class B constructor.
A risk of what?
Post by Lorry Astra
Because I think when
constructor A is executed before constructon B ("B() : A(*this)"),
constructor A uses an object of class B as parameter.
So?
Post by Lorry Astra
But I believe the
object of class B is not generated while constructor A running.
You mean it hasn't been completely constructed yet, yes?
Post by Lorry Astra
So I think
"A(*this)" is a risk.
A risk of *what*?
Post by Lorry Astra
1. A(*this) -> A(B& b)
2. B()
Is that right? Are there any errors in my description?
Yes, plenty. First off, the code is ill-formed. Please fix the code
and ask your question again then. In the mean time read the C++ FAQ,
section 10, question 10.7.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Ulrich Eckhardt
2009-08-06 13:11:50 UTC
Permalink
Post by Lorry Astra
class A{
A(B& b)
{....}
};
class B{
B() : A(*this)
{....}
};
Question here: You seem to be initialising an A as baseclass of B. However,
A is not declared as baseclass. So, is A a baseclass or is it a member?
Post by Lorry Astra
I think here exists a risk in class B constructor. Because I think when
constructor A is executed before constructon B ("B() : A(*this)"),
constructor A uses an object of class B as parameter. But I believe the
object of class B is not generated while constructor A running. So I think
"A(*this)" is a risk.
Right. All subobjects (baseclasses and members) are created before the
containing object is created.

Note that this is not necessarily an error. If A only stores a reference to
the B and later starts to use it, this is not harmful. However, since the B
doesn't yet exist, it must not try to use it at that time.


As per my question above, why does A need a reference to a B? If A is always
a baseclass of B, you could also use a static_cast<B*>(this) inside A to
access B. This technique is typically used by "CRTP", which is wide-spread
even though that, too, is slightly unsafe.

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
David Wilkinson
2009-08-06 13:36:27 UTC
Permalink
Post by Lorry Astra
Dear all,
class A{
A(B& b)
{....}
};
class B{
B() : A(*this)
{....}
};
Please post compilable code, preferably with a simple main() function that shows
how these classes are used.
--
David Wilkinson
Visual C++ MVP
Loading...