Constructors that call other Constructors

D

Dave Rudolf

Hi all,

At the risk of mentioning Java in a C++ news group :), I'm curious if there
is a way to reuse constructors in C++ similar to what can be done in Java.
For instance, in java, I can do the following:

public class Rectangle
{
public Rectangle( int width, int height )
{
// Do stuff here
}

public Rectangle( int widthAndHeight )
{
this( widthAndHeight , widthAndHeight );
}
}

That is, the second constructor simply calls the first to do all of the
dirty work. Is there some similar concept in C++? Certainly, a direct
translation does not work.

Dave
 
A

Alf P. Steinbach

At the risk of mentioning Java in a C++ news group :), I'm curious if there
is a way to reuse constructors in C++ similar to what can be done in Java.
For instance, in java, I can do the following:

public class Rectangle
{
public Rectangle( int width, int height )
{
// Do stuff here
}

public Rectangle( int widthAndHeight )
{
this( widthAndHeight , widthAndHeight );
}
}

That is, the second constructor simply calls the first to do all of the
dirty work. Is there some similar concept in C++? Certainly, a direct
translation does not work.

In C++ use a non-virtual member function e.g. called 'init'. Call that
from each constructor. You cannot do that safely in Java since all
methods in Java are virtual, so Java needs the "constructor reuse"; it's
not needed and therefore not supported in C++.

By the way, this is a FAQ,
<url: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3>.

You should always check the FAQ first before asking here.
 
D

Dan Cernat

Dave Rudolf said:
Hi all,

At the risk of mentioning Java in a C++ news group :), I'm curious if there
is a way to reuse constructors in C++ similar to what can be done in Java.
For instance, in java, I can do the following:

public class Rectangle
{
public Rectangle( int width, int height )
{
// Do stuff here
}

public Rectangle( int widthAndHeight )
{
this( widthAndHeight , widthAndHeight );
}
}

That is, the second constructor simply calls the first to do all of the
dirty work. Is there some similar concept in C++? Certainly, a direct
translation does not work.

Dave

no, one cannot use constructors like you mentioned.
however, there are two solutions to your problem
1. use a common function
class Rectangle
{
private:
void DoStuff(int w, int h)
{
// do the stuff here
}
public:
Rectangle ( int width_and_height)
{
DoStuff(width_and_height, width_and_height);
}
Rectangle ( int w, int h)
{
DoStuff(w, h);
}
};

2. use default values
class Rectangle
{
public:
Rectangle ( int w, int h = GetTheDefaultheightValue())
{
// do stuff with w and h
}

private:
int GetTheDefaultheightValue()
{
rturn 42;
}
};

dan
 
J

Jonathan Turkanis

Dave Rudolf said:
Hi all,

At the risk of mentioning Java in a C++ news group :), I'm curious if there
is a way to reuse constructors in C++ similar to what can be done in Java.
For instance, in java, I can do the following:

public class Rectangle
{
public Rectangle( int width, int height )
{
// Do stuff here
}

public Rectangle( int widthAndHeight )
{
this( widthAndHeight , widthAndHeight );
}
}

That is, the second constructor simply calls the first to do all of the
dirty work. Is there some similar concept in C++? Certainly, a direct
translation does not work.

There has been discussion of adding a mechanism like this to C++,
using the syntax for base initialization:

Rectangle(int widthAndHeight) : Rectangle(widthAndHeight ,
widthAndHeight ) { }

See http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1395.txt.

In your example you could possibly do something like this:

Rectangle(int width, int height = -1)
: width_(width),
height_(height != -1 ? height : width)
{ }

(By the way, in C++ you might want to start thinking along these
lines:

Rectangle( int width, int height )
// Do stuff here
{
// Do stuff here
} )

Jonathan
 
P

Peter Koch Larsen

Dan Cernat said:
no, one cannot use constructors like you mentioned.
however, there are two solutions to your problem
1. use a common function
class Rectangle
{
private:
void DoStuff(int w, int h)
{
// do the stuff here
}
public:
Rectangle ( int width_and_height)
{
DoStuff(width_and_height, width_and_height);
}
Rectangle ( int w, int h)
{
DoStuff(w, h);
}
};

2. use default values
class Rectangle
{
public:
Rectangle ( int w, int h = GetTheDefaultheightValue())
{
// do stuff with w and h
}

private:
int GetTheDefaultheightValue()
{
rturn 42;
}
};

dan

Well.... that second version is a little suspect, isn't it? calling a
memberfunction on a noninitialized object.
 
V

Victor Bazarov

Peter Koch Larsen said:
Well.... that second version is a little suspect, isn't it? calling a
memberfunction on a noninitialized object.

What's noninitialized about 42?
 
D

Dan Cernat

Peter Koch Larsen said:
Well.... that second version is a little suspect, isn't it? calling a
memberfunction on a noninitialized object.

Hmmm, yes, you are right if GetTheDefaultheightValue() tries to use any
members of the object that is in process of constructing at that moment. I
used that example to emphasis the fact that the default arguments aren't
necessarely constants, but can be the result of a function call, as well.

dan
 
P

Peter Koch Larsen

Victor Bazarov said:
What's noninitialized about 42?

Nothing. But look what I wrote. Even though the above construct looks quite
innocent and probably works on actual implementations, my guess is that it
is undefined behaviour if allowed at all.

Kind regards
Peter
 
V

Victor Bazarov

Peter Koch Larsen said:
Nothing. But look what I wrote. Even though the above construct looks quite
innocent and probably works on actual implementations, my guess is that it
is undefined behaviour if allowed at all.

In this particular case, calling a _non_static_ member function is simply
not allowed, you're correct. But if we take our discussion into academics,
why do you say that it would be _undefined_behaviour_?

V
 
D

Dave Rudolf

(By the way, in C++ you might want to start thinking along these
lines:

Rectangle( int width, int height )
// Do stuff here
{
// Do stuff here
} )

Jonathan

Yes, I generally use initialization lists outside of the "code block". The
only exception is when the initialization requires some number crunching.
But I do this because I have been told that it is the right way to write
C++, although you have me curious as to why this is the preferred way to
initialize local fields. Is it an optimization thing ?

Dave
 
V

Victor Bazarov

Dave Rudolf said:
Yes, I generally use initialization lists outside of the "code block". The
only exception is when the initialization requires some number crunching.
But I do this because I have been told that it is the right way to write
C++, although you have me curious as to why this is the preferred way to
initialize local fields. Is it an optimization thing ?

It's covered in the FAQ. See 'Constructors'.

V
 
J

Jonathan Turkanis

Yes, I generally use initialization lists outside of the "code block". The
only exception is when the initialization requires some number crunching.
But I do this because I have been told that it is the right way to write
C++, although you have me curious as to why this is the preferred way to
initialize local fields. Is it an optimization thing ?

By the time you get to rthe body of the constructors, bases and
members have already been initialized. Sometime you are forced to
initialize a base or member explicitly in the initializer list, .e.g.
for const or reference members or types without default constructors
or assignment operators. Even when a type has a default constructor
and assignment operator, default initialization + assignment may not
have the same semantics as direct initialization, and is often less
efficient.

Jonathan
 
M

Martijn Lievaart

Hi all,

At the risk of mentioning Java in a C++ news group :), I'm curious if there
is a way to reuse constructors in C++ similar to what can be done in Java.
For instance, in java, I can do the following:

public class Rectangle
{
public Rectangle( int width, int height )
{
// Do stuff here
}

public Rectangle( int widthAndHeight )
{
this( widthAndHeight , widthAndHeight );
}
}

That is, the second constructor simply calls the first to do all of the
dirty work. Is there some similar concept in C++? Certainly, a direct
translation does not work.

Another technique is to factor out the common behaviour in a base class.
This may seem overkill at first, but in reality is surprisingly often
only an implementation of one-class, one-responsibility.

HTH,
M4
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top