Topic: Reusable Constructors
Author: nr@system.ptv.de (Norbert Riedlin)
Date: 1997/10/21 Raw View
Hi there,
I know I can't do a thing like that:
class X {
public:
X(int x, int y) : _x(x), _y(y)
{};
X() : this(5, 7) // <-- 'this' not allowed here
{};
private:
int _x;
int _y;
};
I think 'this' is not allowed in the marked line, because it hasn't
been constructed yet, but really I just _want_ to construct it!
I know I could have used default parameters here, but that would have
the side effect to create a third constructor with only one parameter.
I also could just copy the first constructor's initializer-list, but
nonono I just don't want to do that (Imagine a much more complex
initializer-list)
Is there no way to call a constructor for 'this' in the
initializer-list?
TIA,
Norbert
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/10/21 Raw View
Norbert Riedlin wrote:
> I know I can't do a thing like that:
>
> class X {
> public:
> X(int x, int y) : _x(x), _y(y)
> {};
> X() : this(5, 7) // <-- 'this' not allowed here
this doesn't make sens.
Write:
X() : X(5, 7) // X::X (int, int) can't be called here
> {};
> private:
> int _x;
> int _y;
Avoid leading underscores.
> };
>
> I think 'this' is not allowed in the marked line, because it hasn't
> been constructed yet, but really I just _want_ to construct it!
this (something) is only allowed if you overload the () operator.
You usually never call an object:
Point p (4, 6);
p (something); // doesn't make sens
> I know I could have used default parameters here, but that would have
> the side effect to create a third constructor with only one parameter.
Right
> I also could just copy the first constructor's initializer-list, but
> nonono I just don't want to do that (Imagine a much more complex
> initializer-list)
>
> Is there no way to call a constructor for 'this' in the
> initializer-list?
Just use a private init member function:
void X::init (int x, int y)
{
_x = x;
_y = y;
}
X::X () { init (5, 7); }
X::X (int x, int y) { init (x, y); }
--
Valentin Bonnard mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://www.pratique.fr/~bonnardv/
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Gerard Weatherby <gerardw@alum.mit.edu>
Date: 1997/10/22 Raw View
Norbert Riedlin wrote:
> I know I can't do a thing like that:
>
> class X {
> public:
> X(int x, int y) : _x(x), _y(y)
> {};
> X() : this(5, 7) // <-- 'this' not allowed here
> {};
> private:
> int _x;
> int _y;
> };
<snip>
> Is there no way to call a constructor for 'this' in the
> initializer-list?
Not that I've ever heard of, but you can get a similar effect with
a base class:
class Y {
protected:
Y(int x, int y) : _x(x), _y(y)
{};
int _x;
int _y;
};
class X : private Y {
public:
X(int x, int y): Y(x,y)
{};
X() : Y(5, 7) // <-- 'Y' allowed here
{};
};
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: David R Tribble <david.tribble@central.beasys.com>
Date: 1997/10/22 Raw View
nr@system.ptv.de (Norbert Riedlin) asked:
> class X
> {
> public:
> X(int x, int y) : _x(x), _y(y) { }
> X() : this(5, 7) { } // <-- 'this' not allowed here
> private:
> int _x;
> int _y;
> };
>
> I think 'this' is not allowed in the marked line, because it hasn't
> been constructed yet, but really I just _want_ to construct it!
> ...
> Is there no way to call a constructor for 'this' in the
> initializer-list?
Unfortunately, no. But by making a simple change in the draft standard,
the following constructor declaration for class X would be legal:
X(): X(5, 7) { } // Call X(int,int) to init members
I quote from the draft, marking the phrase in brackets that could be
changed to make this sort of thing legal:
12.6.2 Initializing bases and members
In the definition of a constructor for a class, initializers for
<<direct and virtual base subobjects>> and nonstatic data members can
be specified by a 'ctor-initializer', which has the form:
...
Names in a 'mem-initializer-id' are looked up in the scope of the
constructor's class and, if not found in that scope, are looked up
in the scope containing the constructor's definition. Unless the
'mem-initializer-id' names a nonstatic data member of the constructor's
class or a <<direct or virtual base of that class>>, the
'mem-initializer' is ill-formed. A 'mem-initializer-list' can
initialize a base class using any name that denotes that base class
type.
...
If we rewrote the clause in brackets to mean "the constructor's class or
a direct or virtual base class of the constructor's class", then it would
be legal to give the class name itself as a member initializer, which
would invoke one of the other class constructors. We would have to add a
restriction that a constructor's mem-initializer-list could not name
itself as one of the mem-initializers (i.e., it must specify a constructor
with a different signature), or else we'd allow infinite looping during
object construction.
Since this change is unlikely to be made to the draft, you probably should
call a common initialization function from both constructors to avoid
duplicating code:
class X
{
public:
X(int x, int y) { init(x, y); } // Call a common func
X() { init(5, 7); } // Call a common func
private:
int _x;
int _y;
void init(int x, int y); // Common func, see below
};
void X::init(int x, int y)
{
// This func is called by all constructors of X
// to initialize the members of X
_x = x;
_y = y;
}
This is not exactly what you had in mind, but it comes close. Be careful,
though, since the object is not fully constructed when X::init() is called.
The initialization function should do little more than initializing the
member variables of the object.
-- David R. Tribble, david.tribble@beasys.com --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/10/22 Raw View
Valentin Bonnard wrote:
>
> Norbert Riedlin wrote:
>
> > I also could just copy the first constructor's initializer-list, but
> > nonono I just don't want to do that (Imagine a much more complex
> > initializer-list)
> >
> > Is there no way to call a constructor for 'this' in the
> > initializer-list?
>
> Just use a private init member function:
>
> void X::init (int x, int y)
> {
> _x = x;
> _y = y;
> }
>
> X::X () { init (5, 7); }
> X::X (int x, int y) { init (x, y); }
While this is the common solution, it doesn't cover all cases.
How would you f.ex. do it with the following?
class MyClass
{
OtherClass& other;
int i;
static OtherClass default_other;
public:
MyClass(OtherClass& oc, int x, int y): other(os), i(x)
{ other.set_attr(y); }
MyClass(): MyClass(default_other, 1, 0) {} // not allowed
};
Of course, you could change the reference to a pointer, but you
might have reasons for using a reference (to express the fact that
it references the same object during the whole lifetime). Making it
a const pointer wouldn't help either, as const member objects have
to be initialized in the initializer list as well.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]