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. 31 5148
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
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++
"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
"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
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
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.
"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
"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
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
"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
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
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
"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
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
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
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
"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
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
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
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
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
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
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?
[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
"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
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++
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++
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
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
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++
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++ This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Alexander Stippler |
last post by:
Hi
I have already posted and discussed the following problems once, but
despite really helpful hints I did not get any further with my problem
(I at least learned, first to exactly consider why...
|
by: david |
last post by:
I have a question (not sure if just a newbie one, or a stupid one)
whose answer I couldn't find on the C# books and tutorials I could put
my hands on.
Consider the following useless class (could...
|
by: david |
last post by:
Well, as a matter of fact I_HAD_MISSED a basic thing or two, anyway,
although Ollie's answer makes perfectly sense when dealing with
classes, it doesn't seem to me to apply as well if you have to...
|
by: Bonj |
last post by:
OK I know a constructor can't have a return value but is it feasible such that I have a class whereby
//in MyClass1.
class MyClass
MyClass1(){}
~MyClass1(){}
MyClass1(int & Result) {Result =...
|
by: Bill Grigg |
last post by:
I have been successfully calling DLL's using VC++ 6.0 and also using VC++7.1
(.NET). I only mention this because I have never felt comfortable with the
process, but nonetheless it did work....
|
by: Edward Diener |
last post by:
Given
value class X
{
public:
// Not allowed: X():i(100000),s(10000) { }
// Allowed
void InitializeDefaults() { i = 100000; s = 10000; }
private:
int i;
|
by: daveb |
last post by:
I'm trying to write some code that calls the constructors of STL
containers explicitly, and I can't get it to compile. A sample program
is below. One compiler complains about the last two lines...
|
by: =?Utf-8?B?UVNJRGV2ZWxvcGVy?= |
last post by:
I have a C# logging assembly with a static constructor and methods that is
called from another C# Assembly that is used as a COM interface for a VB6
Application. Ideally I need to build a file...
|
by: =?Utf-8?B?TmFkYXY=?= |
last post by:
Hi,
I am trying to manually call a constructor of a template argument, the
compiler returns “error C2039: ‘T’ : is not a member...”
How can I manually call the constructor of a...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
|
by: ryjfgjl |
last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
| |