469,306 Members | 1,987 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,306 developers. It's quick & easy.

Calling one constructor from another in VC++

I'm fairly new to C++ and VC++, but for the most part it seems to do most of
the same things that can be done in Java, with just some syntactic and
structural adjustments. However, one thing I haven't been able to figure out
is how to call one constructor from another within a class. It's easy enough
to call the base class's constructor from the derived class, but that's not
what I'm trying to do.

For example, in Java (or J#) it's easy to do this:

public class Circle
{
private int PointX;
private int PointY;
private int Radius;

public Circle()
{
this.PointX = 0;
this.PointY = 0;
this.Radius = 0;
}

public Circle(int x, int y)
{
this();
this.PointX = x;
this.PointY = y;
}

public Circle(int x, int y, int r)
{
this(x, y);
this.Radius = r;
}
}

However, trying to do the same thing in VC++ doesn't work:

// Sphere.h (partial file)
class Sphere
{
public:
Sphere(void);
Sphere(int x, int y);
Sphere(int x, int y, int r);
~Sphere(void);

private:
int PointX;
int PointY;
int Radius;
};

// Circle.cpp (partial file)
#include ".\circle.h"

Circle::Circle(void)
{
this->PointX = 0;
this->PointY = 0;
this->Radius = 0;
}

Circle::Circle(int x, int y)
{
Circle();
this->PointX = x;
this->PointY = y;
}

Circle::Circle(int x, int y, int r)
{
Circle(x, y);
this->Radius = r;
}

In the C++ version, I also tried using this() instead of Circle(), which
caused a compiler error. I also tried doing it without the this-> specifier,
which made no difference. The end result if you call the second constructor
is that the X and Y values have been set, and the Radius is uninitialized.
If you use the third constructor, you get exactly the opposite results. (And
I don't mean they have values of zero; looking at them with the debugger, I
see values of -842150451 for the uninitialized members.)

So is there any way in C++ to let one constructor build on another like
this?

Thanks for any help.
Nov 17 '05 #1
31 4954
Peter E. Granger wrote:
I'm fairly new to C++ and VC++, but for the most part it seems to do
most of the same things that can be done in Java, with just some
syntactic and structural adjustments.
Actually, there are many things you can do in C++ that have no counterpart
in Java at all. You'll discover them in time.
However, one thing I haven't
been able to figure out is how to call one constructor from another
within a class. It's easy enough to call the base class's constructor
from the derived class, but that's not what I'm trying to do.


There's no way to do this in C++. Unlike Java, in C++ at the start of the
first statement of a constructor's body all of the members have been
initialized (their constructors have been run if they have them). In Java
everything gets default initialized before the constructor body is run, and
then the constructor body (perhaps redundantly) initializes everything.

To get the same "constructor re-use" effect in C++, you have to put the
initialization code into a (private/protected) member function and call it
from the constructor(s).

-cd
Nov 17 '05 #2
Peter E. Granger wrote:
I'm fairly new to C++ and VC++, but for the most part it seems to do most of
the same things that can be done in Java, with just some syntactic and
structural adjustments. However, one thing I haven't been able to figure out
is how to call one constructor from another within a class. It's easy enough
to call the base class's constructor from the derived class, but that's not
what I'm trying to do.
<snip>
Circle::Circle(int x, int y)
{
Circle();
The statement above creates a temporary Circle object, which is immediately
destroyed at the end of the statement.
this->PointX = x;
this->PointY = y;
}

Circle::Circle(int x, int y, int r)
{
Circle(x, y);
The statement above creates a temporary Circle object, which is immediately
destroyed at the end of the statement.
this->Radius = r;
}

In the C++ version, I also tried using this() instead of Circle(), which
caused a compiler error. I also tried doing it without the this-> specifier,
which made no difference. The end result if you call the second constructor
is that the X and Y values have been set, and the Radius is uninitialized.
If you use the third constructor, you get exactly the opposite results. (And
I don't mean they have values of zero; looking at them with the debugger, I
see values of -842150451 for the uninitialized members.)

So is there any way in C++ to let one constructor build on another like
this?


Sorry, no. Sometimes you can factor the common initialization out into a
separate init() function, but of course members you don't mention in the
member-initialization list will have been default-constructed by the time
you can call init(). If you have const members, reference members, or
members that don't have default ctors, you must initialize them in each
ctor's member initialization list.

--
Doug Harrison
Microsoft MVP - Visual C++
Nov 17 '05 #3

"Doug Harrison [MVP]" <ds*@mvps.org> wrote in message
news:ct********************************@4ax.com...
Peter E. Granger wrote:
I'm fairly new to C++ and VC++, but for the most part it seems to do most ofthe same things that can be done in Java, with just some syntactic and
structural adjustments. However, one thing I haven't been able to figure outis how to call one constructor from another within a class. It's easy enoughto call the base class's constructor from the derived class, but that's notwhat I'm trying to do.
<snip>
Circle::Circle(int x, int y)
{
Circle();


The statement above creates a temporary Circle object, which is

immediately destroyed at the end of the statement.


Right -- that's what I expected would happen. In fact, I thought I'd said
that in my original message, but I see I omitted it.
So is there any way in C++ to let one constructor build on another like
this?


Sorry, no. Sometimes you can factor the common initialization out into a
separate init() function, but of course members you don't mention in the
member-initialization list will have been default-constructed by the time
you can call init(). If you have const members, reference members, or
members that don't have default ctors, you must initialize them in each
ctor's member initialization list.


That's unfortunate. It's really a handy feature. But you can't get
everything in one, language, I guess.

Thanks for the reply.

- Peter
Nov 17 '05 #4

"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:uq**************@TK2MSFTNGP10.phx.gbl...
Peter E. Granger wrote:
I'm fairly new to C++ and VC++, but for the most part it seems to do
most of the same things that can be done in Java, with just some
syntactic and structural adjustments.
Actually, there are many things you can do in C++ that have no counterpart
in Java at all. You'll discover them in time.


And vice-versa, presumably (like this case).
However, one thing I haven't
been able to figure out is how to call one constructor from another
within a class. It's easy enough to call the base class's constructor
from the derived class, but that's not what I'm trying to do.


There's no way to do this in C++. Unlike Java, in C++ at the start of the
first statement of a constructor's body all of the members have been
initialized (their constructors have been run if they have them). In Java
everything gets default initialized before the constructor body is run,

and then the constructor body (perhaps redundantly) initializes everything.

To get the same "constructor re-use" effect in C++, you have to put the
initialization code into a (private/protected) member function and call it
from the constructor(s).


Thanks, I figured I might end up having to do that. Bit of a nuisance, but
manageable.

Thanks for the reply.

- Peter
Nov 17 '05 #5
Peter E. Granger <PE******@hotmail.com> wrote:
[...]
Actually, there are many things you can do in C++ that have no counterpart
in Java at all. You'll discover them in time.
And vice-versa, presumably (like this case).


I wouldn't expect that much, though.
[...]
To get the same "constructor re-use" effect in C++, you have to put the
initialization code into a (private/protected) member function and call it
from the constructor(s).
Thanks, I figured I might end up having to do that. Bit of a nuisance, but
manageable.


Note that C++ has default parameters which,
AFAIK, where introduced especially to solve
this problem:

class Circle {
public:
Circle(int x=0, int y=0, int r=0)
: PointX(x), PointY(y), Radius(r)
{
}
// ...
};
Thanks for the reply.
HTH,
- Peter

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 17 '05 #6
Peter E. Granger wrote:
"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:uq**************@TK2MSFTNGP10.phx.gbl...
Actually, there are many things you can do in C++ that have no counterpart
in Java at all. You'll discover them in time.


And vice-versa, presumably (like this case).


There is something called "placement new" which in this context
behaves exactly like calling one c-tor from another, but programmers
are discouraged from using it.

Nov 17 '05 #7
"Hendrik Schober" <Sp******@gmx.de> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...

Note that C++ has default parameters which,
AFAIK, where introduced especially to solve
this problem:


Default parameters were introduced because, at the time, there was no such
thing as method overloading. They just happen to also solve some of the
simpler cases of redundant constructors.

Ken
Nov 17 '05 #8
"Mihajlo Cvetanovic" <ma*@RnEeMtOsVeEt.co.yu> wrote in message
news:40**************@RnEeMtOsVeEt.co.yu...

There is something called "placement new" which in this context
behaves exactly like calling one c-tor from another, but programmers
are discouraged from using it.


Placement new is only designed to be used on uninitialized memory. By the
time you get to the first line of a constructor, you have a semi-valid object
in that memory that would be wiped out.

Ken
Nov 17 '05 #9
Ken Alverson <US********@Alverson.net> wrote:
"Hendrik Schober" <Sp******@gmx.de> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...

Note that C++ has default parameters which,
AFAIK, where introduced especially to solve
this problem:
Default parameters were introduced because, at the time, there was no such
thing as method overloading. They just happen to also solve some of the
simpler cases of redundant constructors.


"The original motivation for default parameters
was exactly because a ctor cannot call another
ctor for the same type." (Francis Glassborow)
http://www.google.de/groups?selm=pM5...on.demon.co.uk
I don't have D&E handy here, but I believe that
function overloading was among the very first
features of C++. Wasn't there even an 'overload'
keyword (considered?) ones but later dismissed
because it wasn't needed?

OTOH, I know the first one only from Francis'
posting and the second only from my memory, so
i might be wrong.
Ken


Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 17 '05 #10
"Hendrik Schober" <Sp******@gmx.de> wrote in message
news:e8*************@tk2msftngp13.phx.gbl...
Ken Alverson <US********@Alverson.net> wrote:
"Hendrik Schober" <Sp******@gmx.de> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...

Note that C++ has default parameters which,
AFAIK, where introduced especially to solve
this problem:


Default parameters were introduced because, at the time, there was no such
thing as method overloading. They just happen to also solve some of the
simpler cases of redundant constructors.


"The original motivation for default parameters
was exactly because a ctor cannot call another
ctor for the same type." (Francis Glassborow)
http://www.google.de/groups?selm=pM5...on.demon.co.uk
I don't have D&E handy here, but I believe that
function overloading was among the very first
features of C++. Wasn't there even an 'overload'
keyword (considered?) ones but later dismissed
because it wasn't needed?

OTOH, I know the first one only from Francis'
posting and the second only from my memory, so
i might be wrong.


I could be wrong, and I'm more than willing to admit if I am, but I remember
pretty clearly reading somewhere that the reason we still had default
parameters was backward compatibility with pre-overload code. If overloads
had existed from the get-go, it was argued that default parameters would never
have been created. I'll see if I can find where I read that and see if it has
any credibility.

Ken
Nov 17 '05 #11
This is something that kinda sorta might work, but it's horribly
inefficient:
Circle::Circle(int x, int y, int r)
{
//> Circle(x, y);

Circle temp(x, y);
std::swap(*this, temp); // temp now contains our unitialised values
// and will quietly disappear at the end of
// this scope.
this->Radius = r;
}


I don't recommend this at all. It is cheaper and more readable to hand off
to an init() function. And more efficient than your example as you only set
values once [if we ignore the fact that the members have already been
default initialised to garbage in every case]:

Circle::Circle()
{ init(0, 0, 0); }

Circle::Circle(int x, int y)
{ init(x, y, 0); }

Circle::Circle(int x, int y, int r)
{ init(x, y, r); }

What you are attempting is a Java idiom not a C++ one. Don't be mislead by
superficial similarities in syntax; they are totally different animals. You
should definitely prefer member initialiser lists:

Circle::Circle()
: PointX(0), PointY(0), Radius(0)
{ }

Circle::Circle(int x, int y)
: PointX(x), PointY(y), Radius(0)
{ }

Circle::Circle(int x, int y, int r)
: PointX(x), PointY(y), Radius(r)
{ }

FWIW I learnt Java and C++ the other way around. I find I miss little
things, too: templates, RAII, type safe containers... Ho hum.
Arnold the Aardvark
http://www.codeproject.com/cpp/garbage_collect.asp

Nov 17 '05 #12
Ken Alverson wrote:
I could be wrong, and I'm more than willing to admit if I am, but I
remember pretty clearly reading somewhere that the reason we still had
default
parameters was backward compatibility with pre-overload code.


"Given general function overloading, default arguments are logically
redundant and at best a minor notational convenience. However, C with
Classes had default argument lists for years before general overloading
became avilable in C++." - Stroustrup, D&E, S:2.12.2.
Arnold the Aardvark
http://www.codeproject.com/cpp/garbage_collect.asp

Nov 17 '05 #13
"Arnold the Aardvark" <no@way.com> wrote in message
news:bv*******************@news.demon.co.uk...
Ken Alverson wrote:
I could be wrong, and I'm more than willing to admit if I am, but I
remember pretty clearly reading somewhere that the reason we still had
default
parameters was backward compatibility with pre-overload code.


"Given general function overloading, default arguments are logically
redundant and at best a minor notational convenience. However, C with
Classes had default argument lists for years before general overloading
became avilable in C++." - Stroustrup, D&E, S:2.12.2.


That's the quote I remember, thanks!

Ken
Nov 17 '05 #14
Ken Alverson <US********@Alverson.net> wrote:
[...]
"Given general function overloading, default arguments are logically
redundant and at best a minor notational convenience. However, C with
Classes had default argument lists for years before general overloading
became avilable in C++." - Stroustrup, D&E, S:2.12.2.
That's the quote I remember, thanks!


So I got it wrong.
Now, wait... No! Francis got it wrong! :)
Ken


Schobi

P.S.: Actually... No. This quote still doesn't
say they were not introduced to help with
the problem of redundant constructor code.

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 17 '05 #15
Hendrik Schober wrote:
Ken Alverson <US********@Alverson.net> wrote:
[...]
> "Given general function overloading, default arguments are logically
> redundant and at best a minor notational convenience. However, C with
> Classes had default argument lists for years before general overloading
> became avilable in C++." - Stroustrup, D&E, S:2.12.2.


That's the quote I remember, thanks!


So I got it wrong.
Now, wait... No! Francis got it wrong! :)
Ken


Schobi

P.S.: Actually... No. This quote still doesn't
say they were not introduced to help with
the problem of redundant constructor code.


I didn't have time to skim the whole book, you understand,
but there was something about:

"The default argument list was a very late addition to
the class definition. It was added to curb the proliferation
of identical 'standard argument lists' for class objects
passed as function arguments, ... they can be used to
make class object declarations less verbose and more
similar to struct declarations." - same section.

He's lost me a bit there. :-( 'standard argument lists'?
Arnold the Aardvark
http://www.codeproject.com/cpp/garbage_collect.asp

Nov 17 '05 #16
Ken Alverson wrote:
"Mihajlo Cvetanovic" <ma*@RnEeMtOsVeEt.co.yu> wrote in message
news:40**************@RnEeMtOsVeEt.co.yu...

There is something called "placement new" which in this context
behaves exactly like calling one c-tor from another, but programmers
are discouraged from using it.


Placement new is only designed to be used on uninitialized memory.
By the time you get to the first line of a constructor, you have a
semi-valid object in that memory that would be wiped out.


You'll sometimes see people doing bizarre (but legal) things like:

this->~Foo();
new (this) Foo();

To "re-initialize" an object. You can use this same technique to "call" one
constructor from within another. But don't.

-cd

Nov 17 '05 #17
"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:uW*************@TK2MSFTNGP11.phx.gbl...
Ken Alverson wrote:

Placement new is only designed to be used on uninitialized memory.
By the time you get to the first line of a constructor, you have a
semi-valid object in that memory that would be wiped out.


You'll sometimes see people doing bizarre (but legal) things like:

this->~Foo();
new (this) Foo();


Is that actually legal though? I thought about it, but I wasn't sure if it
was legal to call the destructor before the constructor completed. Either way
it fails if the type of this is really a derived class and not Foo.

Regardless of whether or not it is legal, it's a bad idea, as you noted.

Ken
Nov 17 '05 #18
Arnold the Aardvark <no@way.com> wrote:
[...]
He's lost me a bit there. :-( 'standard argument lists'?
Me too. :)
Arnold the Aardvark


Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 17 '05 #19
Ken Alverson wrote:
"Carl Daniel [VC++ MVP]"
<cp*****************************@mvps.org.nospam > wrote in message
news:uW*************@TK2MSFTNGP11.phx.gbl...
Ken Alverson wrote:

Placement new is only designed to be used on uninitialized memory.
By the time you get to the first line of a constructor, you have a
semi-valid object in that memory that would be wiped out.
You'll sometimes see people doing bizarre (but legal) things like:

this->~Foo();
new (this) Foo();


Is that actually legal though? I thought about it, but I wasn't sure
if it was legal to call the destructor before the constructor
completed.


Yes, it's legal - the object is considered constructed at the start of the
constructor body. Afterall, an exception thrown from within the constructor
body will invoke the destructor.
Either way it fails if the type of this is really a
derived class and not Foo.
Indeed.

Regardless of whether or not it is legal, it's a bad idea, as you
noted.
Yes - it's evil. I've seen it in clever "production" code written by a
fresh young code-jockey who liked to be too clever...

Ken


-cd
Nov 17 '05 #20
Hendrik Schober wrote:
Arnold the Aardvark <no@way.com> wrote:
[...]
He's lost me a bit there. :-( 'standard argument lists'?


Me too. :)


I think what he's talking about is the situation where you have a class that
has several constructors, all of which have a common subset of parameters
(the 'standard argument list'), with each constructor adding one or more
additional arguments beyond that. Default parameters can allow you to
collapse that into fewer constructors.

-cd
Nov 17 '05 #21
Carl Daniel [VC++ MVP] <cp*****************************@mvps.org.nospam > wrote:
[...] the object is considered constructed at the start of the
constructor body. Afterall, an exception thrown from within the constructor
body will invoke the destructor.
Is this true? I didn't think so.
[...]
-cd

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 17 '05 #22
Hendrik Schober wrote:
Carl Daniel [VC++ MVP]
<cp*****************************@mvps.org.nospam > wrote:
[...] the object is considered constructed at the start of the
constructor body. Afterall, an exception thrown from within the
constructor body will invoke the destructor.


Is this true? I didn't think so.


You're right - it's not. Destructors for fully constructed sub-objects will
be invoked.

Nonetheless, I believe that the awful thing I showed up above is technically
legal. Legal or not, it's done it real-world code that I've come across.

-cd
Nov 17 '05 #23
Carl Daniel [VC++ MVP] wrote:
Hendrik Schober wrote:
Arnold the Aardvark <no@way.com> wrote:
[...]
He's lost me a bit there. :-( 'standard argument lists'?


Me too. :)


I think what he's talking about is the situation where you have a class
that has several constructors, all of which have a common subset of
parameters (the 'standard argument list'), with each constructor adding
one or more
additional arguments beyond that. Default parameters can allow you to
collapse that into fewer constructors.


Yes that makes sense, though it sort of contradicts the idea that
default arguments were pre-overloading: He says they were introduced
to curb overloading, but that overloading makes default arguments
redundant. Maybe he meant something else. Um... who cares anyway?
Arnold the Aardvark

'Failure of intelligence' or 'failure of democracy'? They
lied and thousands died, but corporations made money, and
that's all that matters, isn't it?
Nov 17 '05 #24
[I see there have been some other replies to this message in the interim;
probably by now somebody else has hit on the same solution.]

With the help of an ingenious friend (thank you, Theo!), I was able to find
out how to make the constructor calls that I wanted. It's kind of an
odd-looking construct, and since no one here knew about it, I guess it's not
something that's commonly done in C++.

On the off-chance that it'll be useful to someone else, here's the code:

// From file Sphere.h

class Sphere
{
public:
Sphere(void);
Sphere(int x, int y, int z);
Sphere(int x, int y, int z, int r);
~Sphere(void);
System::String *ToString();

private:
int CenterX;
int CenterY;
int CenterZ;
int Radius;
};

// From file Sphere.cpp

Sphere::Sphere(void)
{
this->CenterX = 0;
this->CenterY = 0;
this->CenterZ = 0;
this->Radius = 0;
}

Sphere::Sphere(int x, int y, int z)
{
//Sphere(); // Wrong! Just makes and destroys temp object
this->Sphere::Sphere(); // Right! Initializes all members.
this->CenterX = x;
this->CenterY = y;
this->CenterZ = z;
}

Sphere::Sphere(int x, int y, int z, int r)
{
//Sphere(x, y, z); // Wrong! Just makes and destroys temp object
this->Sphere::Sphere(x, y, z); // Right! Initializes all members.
this->Radius = r;
}

Sphere::~Sphere(void)
{
}

String *Sphere::ToString()
{
String *sReturn = S"";

sReturn = String::Format(S"Sphere is centered at [X={0}, Y={1}, Z={2}]",
CenterX.ToString(), CenterY.ToString(), CenterZ.ToString());
sReturn = String::Concat(sReturn,
String::Format(S"\nSphere has a radius of {0}", Radius.ToString()));

return sReturn;
}

// From file ConstructorTest.cpp

int _tmain()
{
Sphere *sphere1 = new Sphere();
Sphere *sphere2 = new Sphere(10, 100, 1000);
Sphere *sphere3 = new Sphere(5, 50, 500, 5000);

Console::WriteLine(S"Sphere1: {0}", sphere1->ToString());
Console::WriteLine(S"Sphere2: {0}", sphere2->ToString());
Console::WriteLine(S"Sphere3: {0}", sphere3->ToString());
return 0;
}

With the incorrect constructor calls (commented out in the code above), the
result of executing ConstructorTest.exe is:

Sphere1: Sphere is centered at [X=0, Y=0, Z=0]
Sphere has a radius of 0
Sphere2: Sphere is centered at [X=10, Y=100, Z=1000]
Sphere has a radius of -842150451
Sphere3: Sphere is centered at [X=-842150451, Y=-842150451, Z=-842150451]
Sphere has a radius of 5000

But with the correct ones, the result is:

Sphere1: Sphere is centered at [X=0, Y=0, Z=0]
Sphere has a radius of 0
Sphere2: Sphere is centered at [X=10, Y=100, Z=1000]
Sphere has a radius of 0
Sphere3: Sphere is centered at [X=5, Y=50, Z=500]
Sphere has a radius of 5000
Nov 17 '05 #25

"Arnold the Aardvark" <no@way.com> wrote in message
news:bv******************@news.demon.co.uk...
What you are attempting is a Java idiom not a C++ one. Don't be mislead by
superficial similarities in syntax; they are totally different animals.
Just exploring the capabilities of the language. It's a construct that I've
gotten used to, and since I didn't see any mention of it in C++ docs, I
wanted to know if it was available. This was more a curiosity than a crisis.
You should definitely prefer member initialiser lists:

Circle::Circle()
: PointX(0), PointY(0), Radius(0)
{ }

Circle::Circle(int x, int y)
: PointX(x), PointY(y), Radius(0)
{ }

Circle::Circle(int x, int y, int r)
: PointX(x), PointY(y), Radius(r)
{ }
Those look like they could be useful; not something I'd run across in my
reading yet.
FWIW I learnt Java and C++ the other way around. I find I miss little
things, too: templates, RAII, type safe containers... Ho hum.


C++ has been absent from my repertoire of languages for far too long; since
it still seems to be the dominant language for development, I figured it's
about time to correct that.

Thanks for all your help.

- Peter
Nov 17 '05 #26
Peter E. Granger wrote:
[I see there have been some other replies to this message in the interim;
probably by now somebody else has hit on the same solution.]

With the help of an ingenious friend (thank you, Theo!), I was able to find
out how to make the constructor calls that I wanted. It's kind of an
odd-looking construct, and since no one here knew about it, I guess it's not
something that's commonly done in C++.

On the off-chance that it'll be useful to someone else, here's the code:

Sphere::Sphere(int x, int y, int z, int r)
{
//Sphere(x, y, z); // Wrong! Just makes and destroys temp object
this->Sphere::Sphere(x, y, z); // Right! Initializes all members.
this->Radius = r;
}


The above is bogus, both from a Standard C++ point of view and conceptually,
because even if it were legal, it would be equivalent to using placement new
on a partially constructed object and would be wrong for all the reasons
that method is wrong. It's a non-standard leftover from the dark ages of
VC++. Don't use it. You've been given correct answers by myself and others
in this thread.

--
Doug Harrison
Microsoft MVP - Visual C++
Nov 17 '05 #27
Yes, do not use this. It is not guaranteed to continue working. And most
likely will indeed stop working in some future version.

If it is any consolation "delegating constructors" are on the C++ Standards
committee list of the possible feature additions.

Ronald Laeremans
Visual C++ team

"Doug Harrison [MVP]" <ds*@mvps.org> wrote in message
news:l0********************************@4ax.com...
Peter E. Granger wrote:
[I see there have been some other replies to this message in the interim;
probably by now somebody else has hit on the same solution.]

With the help of an ingenious friend (thank you, Theo!), I was able to findout how to make the constructor calls that I wanted. It's kind of an
odd-looking construct, and since no one here knew about it, I guess it's notsomething that's commonly done in C++.

On the off-chance that it'll be useful to someone else, here's the code:

Sphere::Sphere(int x, int y, int z, int r)
{
//Sphere(x, y, z); // Wrong! Just makes and destroys temp object
this->Sphere::Sphere(x, y, z); // Right! Initializes all members.
this->Radius = r;
}
The above is bogus, both from a Standard C++ point of view and

conceptually, because even if it were legal, it would be equivalent to using placement new on a partially constructed object and would be wrong for all the reasons
that method is wrong. It's a non-standard leftover from the dark ages of
VC++. Don't use it. You've been given correct answers by myself and others
in this thread.

--
Doug Harrison
Microsoft MVP - Visual C++

Nov 17 '05 #28
Peter E. Granger <PE******@hotmail.com> wrote:
"Arnold the Aardvark" <no@way.com> wrote in message
news:bv******************@news.demon.co.uk...
What you are attempting is a Java idiom not a C++ one. Don't be mislead by
superficial similarities in syntax; they are totally different animals.
Just exploring the capabilities of the language. It's a construct that I've
gotten used to, and since I didn't see any mention of it in C++ docs, I
wanted to know if it was available. This was more a curiosity than a crisis.


FWIW, when I started to learn C++,
I tried that, too. Unfortunately,
the compiler I used back then did
support it, forcing me to change
the code later.
You should definitely prefer member initialiser lists:

[...]

Those look like they could be useful; not something I'd run across in my
reading yet.


Uh. What are you reading???
[...]
C++ has been absent from my repertoire of languages for far too long; since
it still seems to be the dominant language for development, I figured it's
about time to correct that.
Good idea. :)
Thanks for all your help.

- Peter

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 17 '05 #29
Peter E. Granger <PE******@hotmail.com> wrote:
[I see there have been some other replies to this message in the interim;
probably by now somebody else has hit on the same solution.]
Yes. And hopefully they have abandoned it by now.
With the help of an ingenious friend (thank you, Theo!), I was able to find
out how to make the constructor calls that I wanted. It's kind of an
odd-looking construct, and since no one here knew about it, I guess it's not
something that's commonly done in C++.
1. No, people do know about it.
2. Yes, it isn't done commonly -- and that's
for good reasons.
On the off-chance that it'll be useful to someone else, here's the code:
[snipped code that attempts to call a ctor

on an already constructed object]
Once again, this is the simplest solution
to your problem:

Sphere(int x=0, int y=0, int z=0, int r=0)
: CenterX(x), CenterY(y), CenterZ(z), Radius(r)
{
}

What is tehre to miss?

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 17 '05 #30
Hmmmm. Why do you say that explicit qualification is bogus/illegal from a
Standard C++ point of view? I can buy that using it to call another
constructor on a partially constructed object might be a mistake, but I
question the "even it it were legal" and "its non-standard" assertions.
Explicit qualification appears to be perfectly legal and standard C++. Is
it not? From Section 10.2 "Member name lookup" of the C++ standard

12 Explicit qualification with the scope operator (5.1) suppresses the
virtual call mechanism. [Example:

class B { public: virtual void f(); };

class D : public B { public: void f(); };

void D::f() { /* ... */ B::f(); }

Here, the function call in D::f really does call B::f and not D::f. ]
And there are other places in the standard where explicit qualification is
used to make various points. I easily believe that using explicit
qualification to call one constructor from another is bad, but I would like
to better understand why. My own guess is that it would be bad because it
could cause double invocation of constructors for all nodes of the
inheritance graph and their data members. If that were not anticipated
throughout the entire graph it could result in leaks and hard to find bugs.
Is that why?

The constructor scenario aside, suppose that I want to augment a regular
non-pure virtual method that I am overriding rather than replace it
wholesale. Isn't it perfectly fine to use explicit qualification to supress
the virtual call mechanism in order to invoke base class method
implementation and then add my other additional logic?

-Bern McCarty

"Doug Harrison [MVP]" <ds*@mvps.org> wrote in message
news:l0********************************@4ax.com...
Peter E. Granger wrote:
[I see there have been some other replies to this message in the interim;
probably by now somebody else has hit on the same solution.]

With the help of an ingenious friend (thank you, Theo!), I was able to findout how to make the constructor calls that I wanted. It's kind of an
odd-looking construct, and since no one here knew about it, I guess it's notsomething that's commonly done in C++.

On the off-chance that it'll be useful to someone else, here's the code:

Sphere::Sphere(int x, int y, int z, int r)
{
//Sphere(x, y, z); // Wrong! Just makes and destroys temp object
this->Sphere::Sphere(x, y, z); // Right! Initializes all members.
this->Radius = r;
}
The above is bogus, both from a Standard C++ point of view and

conceptually, because even if it were legal, it would be equivalent to using placement new on a partially constructed object and would be wrong for all the reasons
that method is wrong. It's a non-standard leftover from the dark ages of
VC++. Don't use it. You've been given correct answers by myself and others
in this thread.

--
Doug Harrison
Microsoft MVP - Visual C++

Nov 17 '05 #31
Bern McCarty wrote:
Hmmmm. Why do you say that explicit qualification is bogus/illegal from a
Standard C++ point of view?
I didn't say that.
I can buy that using it to call another
constructor on a partially constructed object might be a mistake, but I
question the "even it it were legal" and "its non-standard" assertions.
Explicit qualification appears to be perfectly legal and standard C++.
You can't directly call a constructor. Thus the following is illegal:
Sphere::Sphere(int x, int y, int z, int r)
{
//Sphere(x, y, z); // Wrong! Just makes and destroys temp object
this->Sphere::Sphere(x, y, z); // Right! Initializes all members.
this->Radius = r;
}

Is it not? From Section 10.2 "Member name lookup" of the C++ standard
See 12.1/2.
And there are other places in the standard where explicit qualification is
used to make various points. I easily believe that using explicit
qualification to call one constructor from another is bad, but I would like
to better understand why. My own guess is that it would be bad because it
could cause double invocation of constructors for all nodes of the
inheritance graph and their data members. If that were not anticipated
throughout the entire graph it could result in leaks and hard to find bugs.
Is that why?
That's certainly one very big reason. This being C++, there may be some more
obscure ones I haven't thought of. :)
The constructor scenario aside, suppose that I want to augment a regular
non-pure virtual method that I am overriding rather than replace it
wholesale. Isn't it perfectly fine to use explicit qualification to supress
the virtual call mechanism in order to invoke base class method
implementation and then add my other additional logic?


Yep.

--
Doug Harrison
Microsoft MVP - Visual C++
Nov 17 '05 #32

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

11 posts views Thread by Alexander Stippler | last post: by
7 posts views Thread by Bonj | last post: by
17 posts views Thread by Bill Grigg | last post: by
6 posts views Thread by daveb | last post: by
7 posts views Thread by =?Utf-8?B?UVNJRGV2ZWxvcGVy?= | last post: by
3 posts views Thread by =?Utf-8?B?TmFkYXY=?= | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by harlem98 | last post: by
1 post views Thread by Geralt96 | last post: by
reply views Thread by harlem98 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.