What's the counterpart of this Java constructing method in C++?

X

xz

Here is a little piece of Java code with two constructors.

SomeClass{
//first constructor
public SomeClass(int x){
...
}

//second constructor
public SomeClass() {
this(0);
}
}

The second one simple use this(0) that calls the first constructor.

I wonder if C++ has the similar thing and how that is done?
 
I

Ian Collins

xz said:
Here is a little piece of Java code with two constructors.

SomeClass{
//first constructor
public SomeClass(int x){
...
}

//second constructor
public SomeClass() {
this(0);
}
}

The second one simple use this(0) that calls the first constructor.

I wonder if C++ has the similar thing and how that is done?

No, constructors can't call other constructors. You have to either
duplicate code or have an initialisation function called by all
constructors.
 
V

Victor Bazarov

Ian said:
No, constructors can't call other constructors. You have to either
duplicate code or have an initialisation function called by all
constructors.

The best solution, of course is to merge the two constructors into one:

class SomeClass {
...
public:
SomeClass(int x = 0) {
...
};

V
 
J

Jeff Schwab

Ian said:
No, constructors can't call other constructors. You have to either
duplicate code or have an initialisation function called by all
constructors.

On the bright side, C++ lets you give the parameter a default value,
such that the two above constructors may be combined as:

struct SomeClass {
SomeClass(int x =0) {
// ...
}
};
 
X

xz

The best solution, of course is to merge the two constructors into one:

    class SomeClass {
        ...
    public:
        SomeClass(int x = 0) {
            ...
    };

V

But this does not always apply.

Sometimes you may want something like the following as in Java:

Coordinate{
//first constructor
public Coordinate(double x, double y, "Descartes"){
...
}

//second constructor
public Coordinate(double rho, double theta, "Polar") {
this(rho*Math.cos(theta), rho*Math.sin(theta),
"Descartes");
}

}
 
I

Ian Collins

xz said:
But this does not always apply.

Sometimes you may want something like the following as in Java:

Coordinate{
//first constructor
public Coordinate(double x, double y, "Descartes"){
...
}

//second constructor
public Coordinate(double rho, double theta, "Polar") {
this(rho*Math.cos(theta), rho*Math.sin(theta),
"Descartes");
}
You could use a single constructor and convert the parameters based on
the coordinate type, something like

struct Coordinate
{
enum Type { Descartes, Polar };

double x,y;

Coordinate( double x, double y, Type type )
: x(type==Descartes ? x : x*cos(y)),
y(type==Descartes ? y : x*sin(y))
{}
};
 
P

Pavel

xz said:
But this does not always apply.

Sometimes you may want something like the following as in Java:

Coordinate{
//first constructor
public Coordinate(double x, double y, "Descartes"){
...
}

//second constructor
public Coordinate(double rho, double theta, "Polar") {
this(rho*Math.cos(theta), rho*Math.sin(theta),
"Descartes");
}

}
Just for the record, the latter constructors should not compile in Java
although I think I understand the point you are trying to make.

I use a private init_() function in C++ to factor out the common code
from the constructors.

Another option is to always have a single constructor with some
versatile value-object as a parameter -- in case you have some
appropriate class available.

This has an advantage that you should not change the prototype and
recompile the client code every time you need to add another flag or
value to the constructor's parameters. Also, there is always one
constructor and same parameter can be often passed to the constructor of
the base class and/or sub-objects.

The drawbacks of this approach are plenty, too (no compile-time type
checking, not everybody has a good value object etc).

-Pavel
 
A

Alf P. Steinbach

* xz:
But this does not always apply.

Sometimes you may want something like the following as in Java:

Coordinate{
//first constructor
public Coordinate(double x, double y, "Descartes"){
...
}

//second constructor
public Coordinate(double rho, double theta, "Polar") {
this(rho*Math.cos(theta), rho*Math.sin(theta),
"Descartes");
}

}

Try something like (disclaimer: off-the-cuff)

class Polar
{
private:
double myRho;
double myTheta;
public:
Polar(): myRho(0), myTheta(0) {}
Polar( double rho, double theta ): myRho( rho ), myTheta( theta ) {}

double rho() const { return myRho; } // Or more elaborate, reducing.
double theta() const { return myTheta; }

// More, like rotation, value operations.
// No modifiers.
};

class Cartesian
{
private:
double myX;
double myY;
public:
Cartesian(): myX(0), myY(0) {}
Cartesian( double x, double y ): myX( x ), myY( y ) {}

double x() const { return myX; }
double y() const { return myY; }

// More, like tranlation, value operations.
};

Cartesian cartesianFrom( Polar const& v ) { ... }
Polar polarFrom( Cartesian const& v ) { ... }

class AngleAsPoint: public Cartesian
{
public:
AngleAsPoint(): myPoint() {}

AngleAsPoint( double rho )
: myRho( rho ), myPoint( cartesianFrom( rho ) )
{}

double rho() const { return myRho; } // Or more elaborate, reducing.
double theta() const { return 1.0; }

Cartesian rotated( Cartesian other ) const
{
return Cartesian(
x()*other.x() - y*other.y(), x()*other.y() + y().other.x()
);
}

AngleAsPoint rotated( AngleAsPoint const& amount ) const
{
return rotated( static_cast<Cartesian const&>( amount ) );
}

// More, value operations.
// No modifiers.
};

class Coordinate: public Cartesian
{
public:
Coordinate(): Cartesian() {}
Coordinate( Polar const& value ): Cartesian( cartesianFrom( value ) ) {}
Coordinate( Cartesian const& value ): Cartesian( value ) {}

Polar asPolar() const { return polarFrom( *this ); }
operator Polar() const { return asPolar(); }

// Polar-specific operations, adapted.
Coordinate rotated( AngleAsPoint const& amount ) const
{
return amount.rotated( *this );
}
};

The above may suffer from premature optimization, because it assumes that
trigonometric operations will be Really Slow relative to basic arithmetic
operations. Which is not necessarily the case on modern computers. Also, I
just fetched some old math up from subconcious (only on my first cup of coffee
here), so you'd better check the math! ;-)

Cheers, & hth.,

- Alf
 
J

James Kanze

Here is a little piece of Java code with two constructors.
SomeClass{
//first constructor
public SomeClass(int x){
...
}
//second constructor
public SomeClass() {
this(0);
}
}
The second one simple use this(0) that calls the first
constructor.
I wonder if C++ has the similar thing and how that is done?

In addition to what others have said, I might add that such a
thing has been added to the current working draft, and will be
part of the next version of C++. The syntax is:

class SomeClass
{
public:
SomeClass( int x ) ...
SomeClass() : SomeClass( 0 ) ...
...
} ;

I've not studied it in detail, but IIRC, the object is
considered "fully constructed" as soon as the first constructor
call returns; i.e. if something in the body of SomeClass() in
the above throws, the destructor will be called.
 
A

Alan Johnson

xz said:
Here is a little piece of Java code with two constructors.

SomeClass{
//first constructor
public SomeClass(int x){
...
}

//second constructor
public SomeClass() {
this(0);
}
}

The second one simple use this(0) that calls the first constructor.

I wonder if C++ has the similar thing and how that is done?

In situations where the class is cheap to copy (which is a property one
should always strive for anyway) my preferred solution is to use static
member functions that act like constructors, while keeping the actual
constructor(s) private. Using your Coordinate example from elsewhere in
this thread:

#include <iostream>
#include <cmath>

class Coordinate
{
private:
double x;
double y;

Coordinate(double x, double y)
: x(x), y(y)
{}

friend std::eek:stream & operator<<(std::eek:stream &,
const Coordinate &);
public:

static Coordinate makeRectangularCoordinate(double x, double y)
{
return Coordinate(x, y);
}

static Coordinate makePolarCoordinate(double rho, double theta)
{
return Coordinate(rho*std::cos(theta), rho*std::sin(theta));
}

};

std::eek:stream & operator<<(std::eek:stream & out, const Coordinate & c)
{
return out << '(' << c.x << ", " << c.y << ')';
}

int main()
{
Coordinate c1 = Coordinate::makeRectangularCoordinate(3.0, 4.0);
Coordinate c2 = Coordinate::makePolarCoordinate(5.0,
std::acos(3.0/5.0));

std::cout << c1 << std::endl;
std::cout << c2 << std::endl;
}
 

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,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top