C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Shared code for multiple consrtuctors
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards
View previous topic :: View next topic  
Author Message
David R Tribble
Guest





PostPosted: Sat May 13, 2006 1:21 am    Post subject: Shared code for multiple consrtuctors Reply with quote



Java has the feature of allowing a constructor to invoke another
constructor within the same class having a different signature.
This is useful for initilializing class members without duplicating a
lot of code, and comes in handy when default function parameters
are not convenient to use.

If C++ had this same feature, it might look something like this:

class Foo
{
int m_a;
int m_b;

public:
Foo(int a)
{
this(-1, a); // Invoke other ctor
}

Foo(int b, int a):
m_a(a), m_b(b)
{ }
};

C++ does not have this feature, but it can be simulated using
placement-new within constructor functions:

Foo(int a)
{
new(this) Foo(-1, a); // Reinitialize *this
}

The only question is, can this be considered a safe thing to do?

-drt

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Gene Bushuyev
Guest





PostPosted: Sat May 13, 2006 2:21 pm    Post subject: Re: Shared code for multiple consrtuctors Reply with quote



"David R Tribble" <david (AT) tribble (DOT) com> wrote in message
news:1147476772.083551.67410 (AT) j73g2000cwa (DOT) googlegroups.com...
Quote:
Java has the feature of allowing a constructor to invoke another
constructor within the same class having a different signature.
This is useful for initilializing class members without duplicating a
lot of code, and comes in handy when default function parameters
are not convenient to use.


If C++ had this same feature, it might look something like this:

class Foo
{
int m_a;
int m_b;

public:
Foo(int a)
{
this(-1, a); // Invoke other ctor
}

Foo(int b, int a):
m_a(a), m_b(b)
{ }
};

This is a trivial example, so writing constructor explicitly doesn't lead to any
inconvinencies:

Foo(int a) : m_a(a), m_b(-1)
{
}

Assuming a hypothetical situation that C++ allowed calling another constructor:

Foo(int a)
// members has been initialized before entering ctor body
{
this(-1, a); // Invoke other ctor

// what is this other constructor invocation supposed to do?
// it cannot undo initialization that has already been performed
// the only reasonable interpretation would be *this = Foo(-1, a);
}

In practice there are situations when some non-trivial functionality has to be
repeated in more than one constructor. If that repetition doesn't involve member
intialization then it can be moved to a separate function. If it does involve
member initialization then it's an indication that your class tries to do too
much and needs an extra level of derivation. Constructor(s) of the base
class(es) provide the pieces of that functionality and derived class(es) can use
them.

Quote:

C++ does not have this feature, but it can be simulated using
placement-new within constructor functions:

Foo(int a)
{
new(this) Foo(-1, a); // Reinitialize *this
}

The only question is, can this be considered a safe thing to do?


I believe this is an undefined behavior, though I'm not absolutely sure without
looking at the Standard.

--
Gene Bushuyev (www.gbresearch.com)
----------------------------------------------------------------
There is no greatness where there is no simplicity, goodness and truth. ~ Leo
Tolstoy

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Tomás
Guest





PostPosted: Sat May 13, 2006 2:21 pm    Post subject: Re: Shared code for multiple consrtuctors Reply with quote



David R Tribble posted:

Quote:
Java has the feature of allowing a constructor to invoke another
constructor within the same class having a different signature.
This is useful for initilializing class members without duplicating a
lot of code, and comes in handy when default function parameters
are not convenient to use.

Two ways.

1) The not-so-good way:


class Monkey {

int k;

char* r;

void CommonConstructor()
{
/* Do the common-denominator stuff in here */
}

public:

Monkey( char* arg_r ) : r(arg_r)
{
/* Do some particular stuff */

CommonConstructor();
}

Monkey( int arg_k ) : k(arg_k)
{
/* Do some particular stuff */

CommonConstructor();
}

};


This runs out of steam however if you have const member objects, or
references as members (assuming you don't want to duplicate code).


2) The better way

/* Start off with a bare-bones base class */

class BB_Monkey {
protected:

int k;

char* const r;

int& j;

public:

BB_Monkey( int const arg_k, char* const arg_r
int& arg_j)
: k(arg_k), r(arg_r), j(arg_j) {}
};


class Monkey : public BB_Monkey {
public:

/* Now put all the fancy constructors
in here, and have them call the
common-denominator base-class constructor */

Monkey( int ) : BB_Monkey(...

};


What you want can be done... I suppose the only question is:

Should it be made more convenient by adding certain functionality to the
language?

-Tomás

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Heinz Ozwirk
Guest





PostPosted: Sat May 13, 2006 4:21 pm    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

"David R Tribble" <david (AT) tribble (DOT) com> schrieb im Newsbeitrag news:1147476772.083551.67410 (AT) j73g2000cwa (DOT) googlegroups.com...
Quote:
Foo(int a)
{
new(this) Foo(-1, a); // Reinitialize *this
}

The only question is, can this be considered a safe thing to do?

NO! Imagine what will happen to Foo's members. They already have been initialized, and they will be initialized again. What happens to pointers and other resources in Foo's members and bases? At best they will leak, but really nasty things might happen, too.

Until C++ allows a secure way to delegate constructor calls, you should simply use a single initialization function that is called from all constructors.

Heinz

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Francis Glassborow
Guest





PostPosted: Sat May 13, 2006 4:21 pm    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

In article <1147476772.083551.67410 (AT) j73g2000cwa (DOT) googlegroups.com>, David
R Tribble <david (AT) tribble (DOT) com> writes
Quote:
Java has the feature of allowing a constructor to invoke another
constructor within the same class having a different signature.
This is useful for initilializing class members without duplicating a
lot of code, and comes in handy when default function parameters
are not convenient to use.

If C++ had this same feature, it might look something like this:

class Foo
{
int m_a;
int m_b;

public:
Foo(int a)
{
this(-1, a); // Invoke other ctor
}

Foo(int b, int a):
m_a(a), m_b(b)
{ }
};

C++ does not have this feature, but it can be simulated using
placement-new within constructor functions:

But as soon as compilers elect to provide extensions (pro tem) of things
that are in the draft (working) paper for the next version of C++ a
constructor will be able to delegate to another constructor of the same
type.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Howard Hinnant
Guest





PostPosted: Sat May 13, 2006 4:21 pm    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

In article <1147476772.083551.67410 (AT) j73g2000cwa (DOT) googlegroups.com>,
"David R Tribble" <david (AT) tribble (DOT) com> wrote:

Quote:
Java has the feature of allowing a constructor to invoke another
constructor within the same class having a different signature.
This is useful for initilializing class members without duplicating a
lot of code, and comes in handy when default function parameters
are not convenient to use.

If C++ had this same feature, it might look something like this:

class Foo
{
int m_a;
int m_b;

public:
Foo(int a)
{
this(-1, a); // Invoke other ctor
}

Foo(int b, int a):
m_a(a), m_b(b)
{ }
};

C++ does not have this feature, but it can be simulated using
placement-new within constructor functions:

Foo(int a)
{
new(this) Foo(-1, a); // Reinitialize *this
}

The only question is, can this be considered a safe thing to do?

Personally I'm a huge fan of this feature. It has been proposed; the
latest paper I'm aware of is:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1895.pdf

My impression is that the EWG has signed off on it and it is before the
CWG. However my personal attention is on the LWG so I could well be
off. However I'm responding because this feature is more valuable in my
own work than you let on. Specifically this feature means that you no
longer have to invent a base class to hold each resource if you want to
construct an object without try/catch all over the place. Instead you
can forward to the nothrow constructor (typically the default) and then
build your object up safe in the knowledge that the destructor will run.

It is a significant advance.

For any class with more than a single resource that it must acquire in a
constructor (e.g. all of the std::containers) it is a significant
simplification in source code and logic.

-Howard

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
David Abrahams
Guest





PostPosted: Sat May 13, 2006 4:21 pm    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

"David R Tribble" <david (AT) tribble (DOT) com> writes:

Quote:
C++ does not have this feature, but it can be simulated using
placement-new within constructor functions:

Foo(int a)
{
new(this) Foo(-1, a); // Reinitialize *this
}

The only question is, can this be considered a safe thing to do?

Not if you have base classes or members with nontrivial destructors,
and you expect them to be called.

Basic concepts 3.8 Object Lifetime

4 A program may end the lifetime of any object by reusing the storage
which the object occupies or by explicitly calling the destructor for
an object of a class type with a non-trivial destructor. For an object
of a class type with a non-trivial destructor, the program is not
required to call the destructor explicitly before the storage which
the object occupies is reused or released; however, if there is no
explicit call to the destructor or if a delete-expression (5.3.5) is
not used to release the storage, the destructor shall not be
implicitly called and any program that depends on the side effects
produced by the destructor has undefined behavior.


If you don't care about efficiency, and you've established enough
invariants of your class to destroy it, you can do:

Foo(int a)
{
this->~Foo(); // Destroy *this
new(this) Foo(-1, a); // Reinitialize *this
}

But either one is a hack. We really need language support for
forwarding constructors. Your best bet is to refactor the common
initialization into a base class:

Foo(int a)
: FooBase(-1,a)
{}

HTH,

--
Dave Abrahams
Boost Consulting
www.boost-consulting.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
David Abrahams
Guest





PostPosted: Sat May 13, 2006 10:21 pm    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

howard.hinnant (AT) gmail (DOT) com (Howard Hinnant) writes:

Quote:
Personally I'm a huge fan of this feature. It has been proposed; the
latest paper I'm aware of is:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1895.pdf

My impression is that the EWG has signed off on it and it is before the
CWG. However my personal attention is on the LWG so I could well be
off. However I'm responding because this feature is more valuable in my
own work than you let on. Specifically this feature means that you no
longer have to invent a base class to hold each resource if you want to
construct an object without try/catch all over the place.

You never had to do that. You could always use a member to hold each
resource, and IMO that will remain best practice for most cases even
after forwarding constructors are available.

Quote:
Instead you can forward to the nothrow constructor (typically the
default) and then build your object up safe in the knowledge that
the destructor will run.

That's kind of two-phase initialization generally doesn't introduce
any safety problems, but it can introduce some inefficiency.

Quote:
It is a significant advance.

For any class with more than a single resource that it must acquire
in a constructor (e.g. all of the std::containers) it is a
significant simplification in source code and logic.

True, it can simplify some code, but it has costs which should not be
ignored completely. I would definitely not recommend it as standard
practice. "One destructor per managed resource" is still a better way
to go, IMO.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Ivan Vecerina
Guest





PostPosted: Sun May 14, 2006 2:21 am    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

"David R Tribble" <david (AT) tribble (DOT) com> wrote in message
news:1147476772.083551.67410 (AT) j73g2000cwa (DOT) googlegroups.com...
: Java has the feature of allowing a constructor to invoke another
: constructor within the same class having a different signature.
: This is useful for initilializing class members without duplicating a
: lot of code, and comes in handy when default function parameters
: are not convenient to use.
:
: If C++ had this same feature, it might look something like this:
:
: class Foo
: {
: int m_a;
: int m_b;
:
: public:
: Foo(int a)
: {
: this(-1, a); // Invoke other ctor
: }
Not quite: the syntax that has been adopted for C++0x is:
Foo(int a) : Foo(-1,a) {}
See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf
and minutes of the meeting where this was adopted:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n1993.html


: C++ does not have this feature, but it can be simulated using
: placement-new within constructor functions:
:
: Foo(int a)
: {
: new(this) Foo(-1, a); // Reinitialize *this
: }
:
: The only question is, can this be considered a safe thing to do?

No: if any data member has a constructor, that constructor will
be called twice. Resources that may have been allocated will
be leaked -- and that's just one of the ways this can go wrong.

--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form



---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Andrei Polushin
Guest





PostPosted: Sun May 14, 2006 2:21 am    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

David R Tribble wrote:
Quote:
Java has the feature of allowing a constructor to invoke another
constructor within the same class having a different signature.
This is useful for initilializing class members without duplicating a
lot of code, and comes in handy when default function parameters
are not convenient to use.

If C++ had this same feature, it might look something like this:

class Foo
{
int m_a;
int m_b;

public:
Foo(int a)
{
this(-1, a); // Invoke other ctor
}

Foo(int b, int a):
m_a(a), m_b(b)
{ }
};

This feature seems to be accepted a month ago, the proposal was
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf
(see the proposal first - it describes current workarounds).

And see the current C++ standard draft, page 233
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2009.pdf


Quote:
C++ does not have this feature, but it can be simulated using
placement-new within constructor functions:

Foo(int a)
{
new(this) Foo(-1, a); // Reinitialize *this
}

The only question is, can this be considered a safe thing to do?

Reinitialize should mean "uninitialize and initialize again", so write
the destructor at least (and consider catching exceptions from it):

Foo(int a)
{
this->~Foo(); // uninitialize
new(this) Foo(-1, a); // initialize
}


--
Andrei Polushin

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Robert Mabee
Guest





PostPosted: Sun May 14, 2006 4:21 am    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

Gene Bushuyev wrote:
Quote:
"David R Tribble" <david (AT) tribble (DOT) com> wrote
Java has the feature of allowing a constructor to invoke another
constructor within the same class having a different signature.

Assuming a hypothetical situation that C++ allowed calling another constructor:

Foo(int a)
// members has been initialized before entering ctor body
{
this(-1, a); // Invoke other ctor

// what is this other constructor invocation supposed to do?
// it cannot undo initialization that has already been performed
// the only reasonable interpretation would be *this = Foo(-1, a);
}

Java's solution is to suppress superclass ctors in this ctor, as
the alternate will perform them. This forces another condition
(on what is already a special case): the explicit ctor has to be
the first thing executed. Thus you would not be allowed C++-style
member initializers at the same time:
Foo (int a) : m_a (a)
{ this (""); // Compiler must reject this
}

I suspect that Java does the hidden initialization (nulling pointers,
setting vtable equivalent) in a hidden way before invoking any ctor,
so there may be other subtle problems for C++, such as any reference
to the object in calling the alternate ctor:
Foo (int a)
{ this (getDefault()); // Compiler should reject this
}
virtual char * getDefault();

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Manfred von Willich
Guest





PostPosted: Mon May 15, 2006 12:22 am    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

Ivan Vecerina wrote:
Quote:
Not quite: the syntax that has been adopted for C++0x is:
Foo(int a) : Foo(-1,a) {}

This provides a neat, intuitive and safe approach.

However, there is another angle on achieving a similar economy of
expression in a similar (not the same) context, as used in Java: allow
initialization of a member to be written in association with the
member, when it will be applied with all constructors (when the
respective initializer should be prohibited). E.g.:

class Foo
{
int m_a;
int m_b = -1;

public:
Foo(int a):
m_a(a)
{ }
Foo(int b, int a):
m_a(a)
{
m_b = b;
}
}

This example is unfortunate in that initializes and then modifies a
member (not what I am wanting to illustrate). When the initialization
is non-trivial and common to all constructors (as I find is the case
all too often), this would be useful, intuitive and succinct.

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Lucas Galfaso
Guest





PostPosted: Mon May 15, 2006 2:21 am    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

Quote:
Dave Abrahams:
If you don't care about efficiency, and you've established enough
invariants of your class to destroy it, you can do:

Foo(int a)
{
this->~Foo(); // Destroy *this
new(this) Foo(-1, a); // Reinitialize *this
}

I might be wrong, but I think this has undefined behavior written all
over it if the destructor is virtual.

Regards,
LG

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
David R Tribble
Guest





PostPosted: Mon May 15, 2006 7:21 pm    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

Ivan Vecerina wrote:
Quote:
Not quite: the syntax that has been adopted for C++0x is:
Foo(int a) : Foo(-1,a) {}


Manfred von Willich wrote:
Quote:
This provides a neat, intuitive and safe approach.

However, there is another angle on achieving a similar economy of
expression in a similar (not the same) context, as used in Java: allow
initialization of a member to be written in association with the
member, when it will be applied with all constructors (when the
respective initializer should be prohibited). E.g.:

class Foo
{
int m_a;
int m_b = -1;
...
};

Yep, this is definitely one of the weaknesses of C++. Unless you
bother to initialize every member of a class in every one of its ctors,
you are left with uninitialized object members.

The usual argument given for this (or against implicit initialization)
is efficiency. E.g., if a member happens to be a large byte array
to be used as a working buffer and does not need to be initialized,
why require the compiler to go through all the trouble of doing so?

The response to that particular argument is, why not provide a
way of overriding implicit member initialization? Something
like (for lack of a better syntax):

class Bar
{
int m_length; // Implicit initialize
int m_count = 1; // Explicit initialize
char m_buf[] default; // Do not initialize
...
};

This removes most of the burden of initializing members, so that
anything not explicitly uninitialized is guaranteed to begin life
in a known state. Objects that don't need initialization can be
specified as such, but require explicit coding by the programmer
to turn off the initialization.

-drt

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
David R Tribble
Guest





PostPosted: Mon May 15, 2006 9:21 pm    Post subject: Re: Shared code for multiple consrtuctors Reply with quote

David R Tribble wrote:
Quote:
Java has the feature of allowing a constructor to invoke another
constructor within the same class having a different signature.
This is useful for initilializing class members without duplicating a
lot of code, and comes in handy when default function parameters
are not convenient to use.

If C++ had this same feature, it might look something like this:

class Foo
{
int m_a;
int m_b;

public:
Foo(int a)
{
this(-1, a); // Invoke other ctor
}

Foo(int b, int a):
m_a(a), m_b(b)
{ }
};


Howard Hinnant wrote:
Quote:
Personally I'm a huge fan of this feature. It has been proposed; the
latest paper I'm aware of is:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1895.pdf


Foo(int a)
: FooBase(-1,a)
{ }


Glad to hear it. The member initializer syntax was actually my first
choice for such a thing, but I was trying to portray the concept using
something similar to Java syntax.

Now if we can just get array member initializers into the language,
too, we'd really have something.

-drt

---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.