 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
JimJ Guest
|
Posted: Tue Dec 09, 2003 10:12 pm Post subject: Invoking constructors at class member initialization |
|
|
My class X (below) wants to call different class member constructors
based on a parameter passed into the class X constructor.
// forward references
class Y;
class Z;
class X
{
public:
X(int type); // constructor
protected:
Y y; // another class
Z z; // another class
};
class Y has two constructors, say. I implement my class X constructor
as follows:
X::X(int type) : ((type == 1) ? Y()) : Y(type)) {}
but this doesn't seem to compile, however I play with the syntax. Can
I not use the ternary conditional operator here or is the problem
related to the invocation of different constructors?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jonathan Turkanis Guest
|
Posted: Wed Dec 10, 2003 11:17 am Post subject: Re: Invoking constructors at class member initialization |
|
|
"JimJ" <james.r.jackson.iii (AT) lmco (DOT) com> wrote
| Quote: | My class X (below) wants to call different class member constructors
based on a parameter passed into the class X constructor.
// forward references
class Y;
class Z;
class X
{
public:
X(int type); // constructor
protected:
Y y; // another class
Z z; // another class
};
class Y has two constructors, say. I implement my class X constructor
as follows:
X::X(int type) : ((type == 1) ? Y()) : Y(type)) {}
but this doesn't seem to compile, however I play with the syntax. Can
I not use the ternary conditional operator here or is the problem
related to the invocation of different constructors?
|
The ? operator is not allowed here. It's a bit like:
int n;
class X : public (n == 1 ? Y : Z ) { };
If Y has a suitable assignment operator, you can use:
X(int n) { if (n == 1) y = Y(1); /*or possibly y = 1; */ }
Otherwise, you could rewrite X:
class X {
public:
X(int type) { y.reset(n == 1 ? new Y(1) : new Y); }
private:
smart_ptr<Y> y;
};
where smart_ptr is a suitable smart pointer template.
Jonathan.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Josephine Schafer Guest
|
Posted: Wed Dec 10, 2003 11:29 am Post subject: Re: Invoking constructors at class member initialization |
|
|
"JimJ" <james.r.jackson.iii (AT) lmco (DOT) com> wrote
| Quote: | My class X (below) wants to call different class member constructors
based on a parameter passed into the class X constructor.
// forward references
class Y;
class Z;
class X
{
public:
X(int type); // constructor
protected:
Y y; // another class
Z z; // another class
};
class Y has two constructors, say. I implement my class X constructor
as follows:
X::X(int type) : ((type == 1) ? Y()) : Y(type)) {}
|
X::X(int type) : y((type == 1) ? Y() : Y(type)) {}
btw, I don't think compiler would be happy just with the forward declarations.
HTH,
J.Schafer
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
JimJ Guest
|
Posted: Wed Dec 10, 2003 8:19 pm Post subject: Re: Invoking constructors at class member initialization |
|
|
Thanks, Josephine - your suggestion worked. I actually misstated my
class X implementation. It should have read
X::X(int type) : ((type == 1) ? y() : y(type)) {}
Note the lower case y (member name, not class name) which now allows
me to see why it wasn't working - it doesn't know what it is supposed
to initialize. I guess I wasn't paying close enough attention to the
special syntax in the constructor initializer list. Thanks.
"Josephine Schafer" <no_spam_josschafer (AT) hotmail (DOT) com> wrote
| Quote: | "JimJ" <james.r.jackson.iii (AT) lmco (DOT) com> wrote in message
news:5e0c8578.0312091307.53d1b4db (AT) posting (DOT) google.com...
My class X (below) wants to call different class member constructors
based on a parameter passed into the class X constructor.
// forward references
class Y;
class Z;
class X
{
public:
X(int type); // constructor
protected:
Y y; // another class
Z z; // another class
};
class Y has two constructors, say. I implement my class X constructor
as follows:
X::X(int type) : ((type == 1) ? Y()) : Y(type)) {}
X::X(int type) : y((type == 1) ? Y() : Y(type)) {}
btw, I don't think compiler would be happy just with the forward declarations.
HTH,
J.Schafer
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jonathan Turkanis Guest
|
Posted: Thu Dec 11, 2003 11:39 am Post subject: Re: Invoking constructors at class member initialization |
|
|
"Josephine Schafer" <no_spam_josschafer (AT) hotmail (DOT) com> wrote in message:
| Quote: | // forward references
class Y;
class Z;
class X
{
public:
X(int type); // constructor
protected:
Y y; // another class
Z z; // another class
};
class Y has two constructors, say. I implement my class X constructor
as follows:
X::X(int type) : ((type == 1) ? Y()) : Y(type)) {}
X::X(int type) : y((type == 1) ? Y() : Y(type)) {}
btw, I don't think compiler would be happy just with the forward
declarations. |
Yes. This solution is more elegant than mine in most cases. Note that it
requires that Y have a copy constructor. If Y has neither a copy-constuctor
nor copy-assignment operator one still needs to switch to pointers, I think.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jonathan Turkanis Guest
|
Posted: Thu Dec 11, 2003 11:43 am Post subject: Re: Invoking constructors at class member initialization |
|
|
"Josephine Schafer" <no_spam_josschafer (AT) hotmail (DOT) com> wrote
| Quote: |
"JimJ" <james.r.jackson.iii (AT) lmco (DOT) com> wrote in message
news:5e0c8578.0312091307.53d1b4db (AT) posting (DOT) google.com...
My class X (below) wants to call different class member constructors
based on a parameter passed into the class X constructor.
// forward references
class Y;
class Z;
class X
{
public:
X(int type); // constructor
protected:
Y y; // another class
Z z; // another class
};
class Y has two constructors, say. I implement my class X constructor
as follows:
X::X(int type) : ((type == 1) ? Y()) : Y(type)) {}
X::X(int type) : y((type == 1) ? Y() : Y(type)) {}
btw, I don't think compiler would be happy just with the forward
declarations.
|
Note that this invokes a Y constructor twice, regardless of the value of
type. In contrast,
X(int type) { if (type == 1) y = Y(type); }
invokes only one Y constructor unless type is 1. Also, your solution assumes
that Y has a copy constructor. If Y has neither copy constructor nor copy
assignment operator, it is necessary to switch to pointers, I believe.
Jonathan
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Thu Dec 11, 2003 8:43 pm Post subject: Re: Invoking constructors at class member initialization |
|
|
In article <br7uj9$dqul$1 (AT) ID-216073 (DOT) news.uni-berlin.de>, Jonathan
Turkanis <technews (AT) kangaroologic (DOT) com> writes
| Quote: | X::X(int type) : y((type == 1) ? Y() : Y(type)) {}
btw, I don't think compiler would be happy just with the forward
declarations.
Note that this invokes a Y constructor twice, regardless of the value of
type.
However the second one is a copy ctor that can be elided in this context |
so is not really an issue.
| Quote: | In contrast,
X(int type) { if (type == 1) y = Y(type); }
|
Which does not do what was asked for:-)
However:
X(int type){if(type != 1) y = Y(type);}
ensures that the default ctor will always be called, and unless type is
1 the Y(int) ctor will also be called followed by the assignment
operator. I find it hard to believe that this would often be an
improvement.
| Quote: |
invokes only one Y constructor unless type is 1. Also, your solution assumes
that Y has a copy constructor. If Y has neither copy constructor nor copy
assignment operator, it is necessary to switch to pointers, I believe.
|
I almost agree with your final sentence except that we could manage with
references:
X(int type): y(type == 1) ? *new Y() : *new Y(type)){}
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Josephine Schafer Guest
|
Posted: Thu Dec 11, 2003 9:18 pm Post subject: Re: Invoking constructors at class member initialization |
|
|
"Jonathan Turkanis" <technews (AT) kangaroologic (DOT) com> wrote
| Quote: |
"Josephine Schafer" <no_spam_josschafer (AT) hotmail (DOT) com> wrote in message
news:br676h$29kclo$1 (AT) ID-192448 (DOT) news.uni-berlin.de...
"JimJ" <james.r.jackson.iii (AT) lmco (DOT) com> wrote in message
news:5e0c8578.0312091307.53d1b4db (AT) posting (DOT) google.com...
My class X (below) wants to call different class member constructors
based on a parameter passed into the class X constructor.
// forward references
class Y;
class Z;
class X
{
public:
X(int type); // constructor
protected:
Y y; // another class
Z z; // another class
};
class Y has two constructors, say. I implement my class X constructor
as follows:
X::X(int type) : ((type == 1) ? Y()) : Y(type)) {}
X::X(int type) : y((type == 1) ? Y() : Y(type)) {}
btw, I don't think compiler would be happy just with the forward
declarations.
Note that this invokes a Y constructor twice, regardless of the value of
type.
|
What makes you think so?
VC++ 7.0 calls the Copy C'tor just once while g++ 3.2 just bypasses the Copy
C'tor!
--
With best wishes,
J.Schafer
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jonathan Turkanis Guest
|
Posted: Fri Dec 12, 2003 9:33 am Post subject: Re: Invoking constructors at class member initialization |
|
|
"Francis Glassborow" <francis (AT) robinton (DOT) demon.co.uk> wrote in message:
| Quote: | Note that this invokes a Y constructor twice, regardless of the value of
type.
However the second one is a copy ctor that can be elided in this context
so is not really an issue.
In contrast,
X(int type) { if (type == 1) y = Y(type); }
Which does not do what was asked for:-)
However:
X(int type){if(type != 1) y = Y(type);}
ensures that the default ctor will always be called, and unless type is
1 the Y(int) ctor will also be called followed by the assignment
operator. I find it hard to believe that this would often be an
improvement.
|
You have a point. I think none of my posts on this matter has been quite
right. I think the correct answer is that it depends on the situation.
Sometimes calling the default constructor when what you really ned is the
result of calling another constructor will have undesirable side effects; in
this the extra call to the copy constructor is a necessary evil. Sometimes
the call to the default constructor is harmless, and depending on the how
often you expect the condition (type == 1) to be true, it may be more
efficient to do the assignment in the body of the constructor.
Thanks for setting me straight.
Jonathan
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jonathan Turkanis Guest
|
Posted: Fri Dec 12, 2003 9:34 am Post subject: Re: Invoking constructors at class member initialization |
|
|
"Josephine Schafer" <no_spam_josschafer (AT) hotmail (DOT) com> wrote
| Quote: |
"Jonathan Turkanis" <technews (AT) kangaroologic (DOT) com> wrote in message
news:br7uj9$dqul$1 (AT) ID-216073 (DOT) news.uni-berlin.de...
Note that this invokes a Y constructor twice, regardless of the value of
type.
What makes you think so?
VC++ 7.0 calls the Copy C'tor just once while g++ 3.2 just bypasses the
Copy
C'tor!
|
You are quite right that my original comments were not well thought out (I
posted a reply to Francis Glassborow to this effect).
Sometimes calls to constructors can be optimized away, and that's good. But
you can't count on it. Before posting, it tried it on VC7.1 with /O2 and
found two constructor calls: one to the default constructor, another to the
copy copnstructor.
Regards,
Jonathan Turkanis
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|