 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Rolf Hemmerling Guest
|
Posted: Tue Apr 20, 2004 10:30 pm Post subject: How to avoid / check typing mistake ":" instead of "::" , w |
|
|
Hello !
Newbie question / problem:
How to avoid / check typing C++ mistake ":" instead of "::", especially
with constructor calls in subclasses ?
This works: The constructor of class A calls the constructor of the
mother class ( as I am used to do so with Java,..).
class B {
B(); }
class A: class B {
A(); }
A::A(){
B::B(); // general initialisiation of all elements also known in B
// anything special of extra elements
}
Now typing mistake:
A::A(){
B:B();
// anything special
}
and "B:" is treated as label, and B() calls itself recursively, and the
program crashes after a while.
Any help or suggestion to avoid/detect such typing mistakes ?
Neither in plain C nor in Java ( and probably not in C# ) such typing
mistakes might cause such crashy behaviour.
I know that such typing mistakes cause same horrorful problems with
FORTH . There it is known as the "fly shit on the program listing"
problem .
In fact, as newbie, it tooks hours to detect the reason for the crash
although in my case it was obvious that it happened after adding a
subclass .
Sincerely
Rolf
--
/ / / Alone on the data highway...
/ / like on an allee in Hannover-Herrenhausen
/ / / The Hemmerling (R) WEB site - Rolf Hemmerling,Germany
/ / / http://www.hemmerling.com/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Teh (tî'pô) Guest
|
Posted: Wed Apr 21, 2004 2:02 pm Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
Rolf Hemmerling bravely attempted to attach 55 electrodes of knowledge
to the nipples of comp.lang.c++.moderated by saying:
| Quote: |
This works: The constructor of class A calls the constructor of the
mother class ( as I am used to do so with Java,..).
class B {
B(); }
class A: class B {
A(); }
A::A(){
B::B(); // general initialisiation of all elements also known in B
// anything special of extra elements
}
|
This is wrong, what you're actually doing is constructing a nameless
temporary of type B inside A's constructor while B's A part is
constructed by the default constructor.
You want initialization lists.
A::A() : B() { }
In the case of default constructor this is redundant BTW.
Example:
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "tA(void)n"; }
A(int) { cout << "tA(int)n"; }
A(double) { cout << "tA(double)n"; }
};
class B : public A
{
public:
B(int);
B(double);
};
B::B(int i)
{
A(+i); // need the + otherwise compiler thinks we're
// redeclaring i as an A
}
B::B(double d) : A(d)
{
}
int main()
{
cout << "Wrong way:n";
B b1(0);
cout << "Right way:n";
B b2(0.0);
return 0;
}
This will print:
Wrong way:
A(void) => b1's A base class
A(int) => local A in B(int) ctor
Right way:
A(double) => b2's A base class
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Michiel Salters Guest
|
Posted: Wed Apr 21, 2004 3:49 pm Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
Rolf Hemmerling <hemmerling (AT) gmx (DOT) net> wrote
| Quote: | Hello !
Newbie question / problem:
How to avoid / check typing C++ mistake ":" instead of "::", especially
with constructor calls in subclasses ?
This works: The constructor of class A calls the constructor of the
mother class ( as I am used to do so with Java,..).
class B {
B(); }
class A: class B {
A(); }
A::A(){
B::B(); // general initialisiation of all elements also known in B
// anything special of extra elements
}
|
No, it doesn't. You create a temporary B object, using the no-argument
B constructor. It's not used, and destroyed before A exits. Also,
because you didn't specify which constructor to use to create the
real base class object, B::B is called again with no arguments.
This is done automatically, as your base object must be initialized.
The syntax you need is
A::A ( ) : B( ) { /***/ }
This matters especially if B does not have a default ctor, or you want
to use another ctor, in which case you'd call A::A() : B( arguments )
Regards,
Michiel Salters
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Falk Tannhäuser Guest
|
Posted: Wed Apr 21, 2004 7:32 pm Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
Rolf Hemmerling wrote:
| Quote: | This works: The constructor of class A calls the constructor of the
mother class ( as I am used to do so with Java,..).
class B {
B(); }
class A: class B {
A(); }
A::A(){
B::B(); // general initialisiation of all elements also known in B
// anything special of extra elements
}
Now typing mistake:
A::A(){
B:B();
// anything special
}
and "B:" is treated as label, and B() calls itself recursively, and the
program crashes after a while.
Any help or suggestion to avoid/detect such typing mistakes ?
I think you didn't post the exact code causing problems. In order |
to compile, I had to modify it as this:
____________________________________________________
class B
{
public:
B() {}
};
class A: public B
{
public:
A();
};
A::A()
{
#if 0
B::B(); // general initialisiation of all elements also known in B
// anything special of extra elements
#else
B:B();
// anything special
#endif
}
int main()
{
A a;
return 0;
}
____________________________________________________
Neither of both variants should crash, they are in fact equivalent.
The variant with a single ":" causes gcc 3.3.1 to generate a warning
"label `B' defined but not used" but the true problem isn't there.
In fact both variants are correct, well defined C++ code, but neither
one does what you want it to do.
The statement
B::B();
or
B(); // with or without preceding label
in the constructor body will simply construct an anonymous object
of type B (having nothing to to with the B subobject within the A
object being constructed), which will be destroyed right afterwards.
The correct syntax to initialize the B subobject is:
A::A()
: B()
{
// ...
}
The good news is that if you omit this call, the compiler will
automatically insert it for you (or complain if a parameterless
constructor for B is not existing or not accessible); you simply
can't construct an A without constructing its B subobject.
You can put traces (like std::cout << "Hello from ...") in the
constructors of B and A (before and after the superfluous call
to B()) as well as add destructors with traces to both classes
if you want to verify what I said.
Falk
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Wed Apr 21, 2004 7:34 pm Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
Rolf Hemmerling <hemmerling (AT) gmx (DOT) net> wrote
| Quote: | Newbie question / problem:
How to avoid / check typing C++ mistake ":" instead of "::",
especially with constructor calls in subclasses ?
|
There aren't many cases where both are legal; generally, if you make a
mistake, the compiler will complain.
| Quote: | This works: The constructor of class A calls the constructor of the
mother class ( as I am used to do so with Java,..).
|
Note however that the syntax for doing so is quite different than that
of Java.
| Quote: | class B {
B(); }
class A: class B {
|
I presume you mean "class A : public B" here. What you've actually
written isn't legal C++.
| Quote: | A(); }
A::A(){
B::B(); // general initialisiation of all elements also known in B
|
This statement creates a temporary B on the stack, then destroys it. It
does nothing with the B which is a base of A.
The compiler automatically calls the constructor for all base classes
and all members before entering the constructor of A. If the default
constructors of the base classes or members is sufficient, then you
don't have to do anything. (This is exactly like Java.) You are only
concerned if a base class or a member requires a parameter. In this
case, you must specify how the constructor is to be called *before*
entering your own constructor (and not as the first statement in the
constructor, as is the case in Java). Thus:
A::A()
: B( someInitializer )
{
}
The syntactical structure used is called a constructor initializer.
Look it up. You'll use it a lot if you're writing C++.
| Quote: | // anything special of extra elements
}
Now typing mistake:
A::A(){
B:B();
// anything special
}
and "B:" is treated as label, and B() calls itself recursively, and
the program crashes after a while.
|
Actually, in this case, there is no difference. B::B() is the same
thing as B(), and labels are in a different namespace, so the label B
doesn't hide the name of the class B. Again, you create a temporary B,
then destroy it, without doing anything with it.
This is also the behavior I get with the three compilers I actually have
access to (Sun CC 5.1, g++ 3.2.2 and VC++ 6.0).
| Quote: | Any help or suggestion to avoid/detect such typing mistakes ?
Neither in plain C nor in Java ( and probably not in C# ) such typing
mistakes might cause such crashy behaviour.
|
In both C++ and Java, typing mistakes which affect scope can cause
problems, due to function overloading. C++ might be more sensitive than
Java with regards to this -- I've not found it a problem with either
language.
| Quote: | I know that such typing mistakes cause same horrorful problems with
FORTH . There it is known as the "fly shit on the program listing"
problem .
In fact, as newbie, it tooks hours to detect the reason for the crash
although in my case it was obvious that it happened after adding a
subclass .
|
I'm still trying to figure out what your real problem is. There's
nothing in what you wrote which could cause infinit recursion. What you
wrote doesn't do what you expect it to, but that has nothing to do with
the typing error -- with or without the typing error, you should get the
same behavior.
FWIW: it is possible to create a situation where such a typing error
does cause a run-time problem:
void f() { std::cout << "Non" ; }
class B
{
public:
static void f() { std::cout << "OKn" ; }
} ;
void g()
{
B::f() ; // Displays "OK". If I mistype and only have
// one :, displays "No".
}
In practice, such problems are rare, since we generally give our
functions more meaningful names than f, and the probability of an actual
name class, like here, is very small. And if I write B:f(), and there
is no f() in global scope, the compiler complains.
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Vladimír Marko Guest
|
Posted: Thu Apr 22, 2004 12:21 am Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
Your example of typing mistake is not a good one, bases
are initialised in a different manner, namely
A::A()
: B() // initialise bases (and members)
{
// other initialisation if necessary
}
There is no room for mistakes here.
The problem you describe may arise in a few slightly
different cases. In fact, this one is the easiest to trace:
// case 1:
struct B{ void foo() { } };
struct A : B { void foo(); };
void A::foo()
{
B:foo(); // typing mistake -> infinite recursion
}
int main() { A a; a.foo(); return 0; }
The program simply crashes (or freezes if some smart
compiler optimizes the tail recursion into a loop). It is
much worse if the typing mistake causes "only" a call
to the wrong function. It creates a hard-to-trace-bug
that may often show up at seemingly unrelated code:
// case 2:
struct B { static void foo() { } }; // first foo()
void foo() { } // second foo();
struct A { void foo2(); };
void A::foo2(){
B:foo(); // typing mistake -> wrong foo() called
}
int main(){ A a; a.foo2(); return 0; }
Just imagine that foo() makes some reference counting
(incref or decref) and you may get an access to a freed
resource without any idea why was it freed.
My suggestions to avoid such errors are:
case1:
Use "this->B::foo();" to invoke a Base class's method.
If you type ":" instead of "::" you get a compile time
error. This can be used whenever a derived class's
function needs to use a base class's function that's
overridden in the derived class. I believe that such
constructs are error-prone and should not be used
at all (add "virtual" to B::foo() and A::foo() gets called
recursively anyway).
case 2:
The problem with this "B::foo()" is that there is ::foo()
visible in current scope. If you are using more functions
with the same name and a similar (implicit conversions!)
prototype make sure that either the correct one or none
is visible whenever you use it. With regard to this,
one should avoid placing anything in the global scope
and "using namespace ..." (even std).
Vladimir Marko
PS: comments to your code:
"Rolf Hemmerling" <hemmerling (AT) gmx (DOT) net> wrote
| Quote: | Hello !
Newbie question / problem:
How to avoid / check typing C++ mistake ":" instead of "::", especially
with constructor calls in subclasses ?
This works: The constructor of class A calls the constructor of the
mother class ( as I am used to do so with Java,..).
class B {
B(); }
change "class" to "struct" and add a definition of "B::B()" |
next time to allow copy-paste-compile
| Quote: |
class A: class B {
parse error - omit the second "class"
A(); }
A::A(){
base B is default-initialised
B::B(); // general initialisiation of all elements also known in B
this creates an unnamed temporary object of class B |
which is then destroyed
| Quote: | // anything special of extra elements
}
Now typing mistake:
A::A(){
base B is again default-initialised
B:B();
again a temporary object of class B
// anything special
}
and "B:" is treated as label, and B() calls itself recursively, and the
program crashes after a while.
no, this would be the case with member function, not with |
the constructor that creates an unnamed temporary
| Quote: |
Any help or suggestion to avoid/detect such typing mistakes ?
[snip]
Sincerely
Rolf
[snip] |
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Teh (tî'pô) Guest
|
Posted: Fri Apr 23, 2004 12:20 am Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] proclaimed:
| Quote: |
and "B:" is treated as label, and B() calls itself recursively, and
the program crashes after a while.
Actually, in this case, there is no difference. B::B() is the same
thing as B(), and labels are in a different namespace, so the label B
doesn't hide the name of the class B. Again, you create a temporary B,
then destroy it, without doing anything with it.
|
That's what I thought (and posted) too. On third thought B::B() is a
explicit call to a constructor and not creation of a temporary
therefor it should illegal. CC and Comeau online seem to back this up.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Sat Apr 24, 2004 12:09 am Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
"Teh (tî'pô)" <teh (AT) mindless (DOT) com> wrote
| Quote: | kanze (AT) gabi-soft (DOT) fr proclaimed:
and "B:" is treated as label, and B() calls itself recursively, and
the program crashes after a while.
Actually, in this case, there is no difference. B::B() is the same
thing as B(), and labels are in a different namespace, so the label B
doesn't hide the name of the class B. Again, you create a temporary
B, then destroy it, without doing anything with it.
That's what I thought (and posted) too. On third thought B::B() is a
explicit call to a constructor and not creation of a temporary
therefor it should illegal. CC and Comeau online seem to back this up.
|
Is it? I don't think that there is such a thing as an explicit call to
a constructor in the language. In §5.2.3 we read that "A
simple-type-specifier (7.1.5) followed by a parenthesized
expression-list constructs a value of the specified type." In §8.1.5,
one of the productions of a simple-type-specifier is
nested-name-specifier[opt] type-name. In this case, the
nested-name-specifier is B::. Because the name of a class is injected
into the class, a look-up of B after B:: should find the type name B.
At least, that's my somewhat naïve impression. Is there any reason why
the compiler shouldn't find the injected name in this case?
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Moore Guest
|
Posted: Sun Apr 25, 2004 11:15 pm Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
"Teh (tî'pô)" <teh (AT) mindless (DOT) com> wrote
| Quote: | kanze (AT) gabi-soft (DOT) fr proclaimed:
and "B:" is treated as label, and B() calls itself recursively, and
the program crashes after a while.
Actually, in this case, there is no difference. B::B() is the same
thing as B(), and labels are in a different namespace, so the label B
doesn't hide the name of the class B. Again, you create a temporary B,
then destroy it, without doing anything with it.
That's what I thought (and posted) too. On third thought B::B() is a
explicit call to a constructor and not creation of a temporary
therefor it should illegal. CC and Comeau online seem to back this up.
|
Are you sure about that? If you see compile-time errors from the
OP's code, I expect the problem is that the OP declared the ctor for B
as private in his example, thus it is not accessible to class A. If
you declare the class B ctor public or protected, then everything
should work fine for either the B::B() or B:B() syntax (of course
neither gives the behavior described by the OP, as already pointed out
in this thread).
Once the class B ctor is declared public or private I only get
link-time errors with GCC (versions 3.2, 3.3 and 3.4) and I think this
is correct. The B:: is just a scope-qualifier, which disambiguates
the call in the case where there is another function named B() in
scope.
Finally, with the latter example B:B(), compiling at the highest
warning level in GCC (-Wall), gives a warning that "label 'B' defined
but not used", which should quickly help the OP find his problem.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Teh (tî'pô) Guest
|
Posted: Mon Apr 26, 2004 8:26 am Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
Dave Moore proclaimed:
| Quote: | "Teh (tî'pô)" <teh (AT) mindless (DOT) com> wrote
[email]kanze (AT) gabi-soft (DOT) fr[/email] proclaimed:
and "B:" is treated as label, and B() calls itself recursively, and
the program crashes after a while.
Actually, in this case, there is no difference. B::B() is the same
thing as B(), and labels are in a different namespace, so the label B
doesn't hide the name of the class B. Again, you create a temporary B,
then destroy it, without doing anything with it.
That's what I thought (and posted) too. On third thought B::B() is a
explicit call to a constructor and not creation of a temporary
therefor it should illegal. CC and Comeau online seem to back this up.
Are you sure about that?
|
I'm sure of increasingly less things since I've started reading this
group regularly.
[...]
| Quote: |
Once the class B ctor is declared public or private I only get
link-time errors with GCC (versions 3.2, 3.3 and 3.4) and I think this
is correct. The B:: is just a scope-qualifier, which disambiguates
the call in the case where there is another function named B() in
scope.
|
I don't have a good enough grasp of the standard to say, if both James
Kanze and yourself say it's a valid way of qualifying the scope you're
probably right in which case Comeau seems to be wrong.
This code:
struct A {
A() {}
};
int main()
{
A::A();
}
produces this error (on Comeau online):
"ComeauTest.c", line 7: error: a constructor or destructor may not
have its address
taken
A::A();
^
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Moore Guest
|
Posted: Mon Apr 26, 2004 10:13 pm Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
"Teh (tî'pô)" <teh (AT) mindless (DOT) com> wrote
| Quote: | Dave Moore proclaimed:
"Teh (tî'pô)" <teh (AT) mindless (DOT) com> wrote
[email]kanze (AT) gabi-soft (DOT) fr[/email] proclaimed:
and "B:" is treated as label, and B() calls itself recursively, and
the program crashes after a while.
Actually, in this case, there is no difference. B::B() is the same
thing as B(), and labels are in a different namespace, so the label B
doesn't hide the name of the class B. Again, you create a temporary B,
then destroy it, without doing anything with it.
That's what I thought (and posted) too. On third thought B::B() is a
explicit call to a constructor and not creation of a temporary
therefor it should illegal. CC and Comeau online seem to back this up.
Are you sure about that?
I'm sure of increasingly less things since I've started reading this
group regularly.
|
I know exactly how you feel 8*).
| Quote: | [...]
Once the class B ctor is declared public or private I only get
link-time errors with GCC (versions 3.2, 3.3 and 3.4) and I think this
is correct. The B:: is just a scope-qualifier, which disambiguates
the call in the case where there is another function named B() in
scope.
I don't have a good enough grasp of the standard to say, if both James
Kanze and yourself say it's a valid way of qualifying the scope you're
probably right in which case Comeau seems to be wrong.
|
Well .. I can't speak for James Kanze, but if you pit me against
Comeau, my money is on Comeau 101 times out of 100, so your statement
above made me suspicious ...
| Quote: | This code:
struct A {
A() {}
};
int main()
{
A::A();
}
produces this error (on Comeau online):
"ComeauTest.c", line 7: error: a constructor or destructor may not
have its address
taken
A::A();
^
|
And with good reason ... a check of the Standard (section 12.1/2)
reveals:
"A constructor is used to initialize objects of its class type.
Because constructors do not have names, they are never found during
name lookup; however an explicit type conversion using the functional
notation (5.2.3) will cause a constructor to be called to initialize
an object. [Note: for initialization of objects of class type see
12.6. ]"
Thus, the statement A::A() from your example above, is properly
interpreted by Comeau as an attempt to take the address of the
constructor, which is not allowed (c.f. 12.1/12 of the Standard).
So, it seems that as expected, Comeau is right and I am wrong .. whew!
FWIW, GCC 3.3.1 and 3.4.0 accept your example without complaint ...
but I'd probably still go with Comeau on this one.
Cheers,
Dave Moore
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Tue Apr 27, 2004 4:46 pm Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
[email]dtmoore (AT) rijnh (DOT) nl[/email] (Dave Moore) wrote in message
news:<306d400f.0404260551.62d20a55 (AT) posting (DOT) google.com>...
| Quote: | "Teh (tî'pô)" <teh (AT) mindless (DOT) com> wrote in message
news:<shap801jii3dsls8k45hflieus477pi7or (AT) 4ax (DOT) com>...
Dave Moore proclaimed:
"Teh (tî'pô)" <teh (AT) mindless (DOT) com> wrote in message
news:<ikne8018nt256mkifm9uh1igg21k2mcnjf (AT) 4ax (DOT) com>...
[email]kanze (AT) gabi-soft (DOT) fr[/email] proclaimed:
and "B:" is treated as label, and B() calls itself
recursively, and the program crashes after a while.
Actually, in this case, there is no difference. B::B() is the
same thing as B(), and labels are in a different namespace, so
the label B doesn't hide the name of the class B. Again, you
create a temporary B, then destroy it, without doing anything
with it.
That's what I thought (and posted) too. On third thought B::B()
is a explicit call to a constructor and not creation of a
temporary therefor it should illegal. CC and Comeau online seem
to back this up.
Are you sure about that?
I'm sure of increasingly less things since I've started reading this
group regularly.
I know exactly how you feel 8*).
[...]
Once the class B ctor is declared public or private I only get
link-time errors with GCC (versions 3.2, 3.3 and 3.4) and I think
this is correct. The B:: is just a scope-qualifier, which
disambiguates the call in the case where there is another function
named B() in scope.
I don't have a good enough grasp of the standard to say, if both
James Kanze and yourself say it's a valid way of qualifying the
scope you're probably right in which case Comeau seems to be wrong.
Well .. I can't speak for James Kanze, but if you pit me against
Comeau, my money is on Comeau 101 times out of 100, so your statement
above made me suspicious ...
|
Comeau is probably right more often than most compilers, but I still
trust a statement from the experts more than any compiler. (About what
the standard says, obviously. About what I can actually do in a
program, well, like it or not, the compiler has the final say.) But
until now, none of the real experts seem to have weighed in.
| Quote: | This code:
struct A {
A() {}
};
int main()
{
A::A();
}
produces this error (on Comeau online):
"ComeauTest.c", line 7: error: a constructor or destructor may not
have its address
taken
A::A();
^
And with good reason ... a check of the Standard (section 12.1/2)
reveals:
"A constructor is used to initialize objects of its class type.
Because constructors do not have names, they are never found during
name lookup; however an explicit type conversion using the functional
notation (5.2.3) will cause a constructor to be called to initialize
an object. [Note: for initialization of objects of class type see
12.6. ]"
Thus, the statement A::A() from your example above, is properly
interpreted by Comeau as an attempt to take the address of the
constructor, which is not allowed (c.f. 12.1/12 of the Standard).
|
I'm not sure I understand. First, how is the above an attempt to take
the address of the constructor. I don't see any attempt to take the
address of anything. And second, given the passage you quoted, the
statement in question *doesn't* name the constructor. It looks up A in
the scope of A -- because of name injection, it finds an A -- the name
of the class itself. Having found the name of a class, it would seem
that we are dealing with a type conversion using the functional
representation, so the expression "will cause a constructor to be called
to initialize an object."
I'm not 100% sure -- I think that there are various restrictions with
regards to the injected name, and whether it is or it is not found
during different types of name lookup. But I am sure that there is no
way that this expression can be interpreted as an attempt to take the
address of anything. Or at least, I think I am.
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Vladimír Marko Guest
|
Posted: Wed Apr 28, 2004 9:19 am Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
"Dave Moore" <dtmoore (AT) rijnh (DOT) nl> wrote
| Quote: | "Teh (tî'pô)" <teh (AT) mindless (DOT) com> wrote
Dave Moore proclaimed:
"Teh (tî'pô)" <teh (AT) mindless (DOT) com> wrote
[email]kanze (AT) gabi-soft (DOT) fr[/email] proclaimed:
[snip]
struct A {
A() {}
};
int main()
{
A::A();
}
produces this error (on Comeau online):
"ComeauTest.c", line 7: error: a constructor or destructor may not
have its address
taken
A::A();
^
And with good reason ... a check of the Standard (section 12.1/2)
reveals:
"A constructor is used to initialize objects of its class type.
Because constructors do not have names, they are never found during
name lookup; however an explicit type conversion using the functional
notation (5.2.3) will cause a constructor to be called to initialize
an object. [Note: for initialization of objects of class type see
12.6. ]"
Thus, the statement A::A() from your example above, is properly
interpreted by Comeau as an attempt to take the address of the
constructor, which is not allowed (c.f. 12.1/12 of the Standard).
So, it seems that as expected, Comeau is right and I am wrong .. whew!
FWIW, GCC 3.3.1 and 3.4.0 accept your example without complaint ...
but I'd probably still go with Comeau on this one.
Cheers,
Dave Moore
|
I think that "constructors ... are never found during
name lookup" is pretty clear. Comeau ignores this
and finds the constructor which should NEVER be
found. After that it's pretty clear that the paragraph
9-2 (before 9.1) should be applied:
-2- A class-name is inserted into the scope in which
it is declared immediately after the class-name is seen.
The class-name is also inserted into the scope of the
class itself. [snip]
Thus, 'A::A' is equivalent to 'struct A' in this case
and Comeau is definitely wrong.
Cheers,
Vladimir Marko
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Moore Guest
|
Posted: Fri Apr 30, 2004 11:16 am Post subject: Re: How to avoid / check typing mistake ":" instead of "::" |
|
|
"Vladimír Marko" <vm (AT) nowhere (DOT) invalid> wrote
| Quote: | "Dave Moore" <dtmoore (AT) rijnh (DOT) nl> wrote in message
news:306d400f.0404260551.62d20a55 (AT) posting (DOT) google.com...
"A constructor is used to initialize objects of its class type.
Because constructors do not have names, they are never found during
name lookup; however an explicit type conversion using the functional
notation (5.2.3) will cause a constructor to be called to initialize
an object. [Note: for initialization of objects of class type see
12.6. ]"
Thus, the statement A::A() from your example above, is properly
interpreted by Comeau as an attempt to take the address of the
constructor, which is not allowed (c.f. 12.1/12 of the Standard).
|
snip
| Quote: |
I think that "constructors ... are never found during
name lookup" is pretty clear. Comeau ignores this
and finds the constructor which should NEVER be
found.
|
Of course it does .. I don't know what I was thinking .. shouldn't
post so late at night I guess 8*).
| Quote: | After that it's pretty clear that the paragraph
9-2 (before 9.1) should be applied:
-2- A class-name is inserted into the scope in which
it is declared immediately after the class-name is seen.
The class-name is also inserted into the scope of the
class itself. [snip]
Thus, 'A::A' is equivalent to 'struct A' in this case
|
I guess this is correct, even though it means infinitely recursive
qualified-ids like:
A::A::A::A -- as far as you want to go -- ::A();
are allowed. Maybe this is one for "Stupid C++ tricks".
| Quote: | and Comeau is definitely wrong.
|
Well ... I guess I have to re-adjust my betting strategy and only take
Comeau 100 times out of 100. <grin>
Dave Moore
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|