Topic: Inheritance and operator =
Author: Steve Clamage <stephen.clamage@sun.com>
Date: Wed, 24 Jan 2001 23:14:02 GMT Raw View
James Kuyper wrote:
>
> Pete Kirman wrote:
> >
> > But in this case I am not using an operator that is taking the same
> > arguments as the compiler generated method, so surely I'm using the
> > overloading capabilities of the language to provide two operators in the
> > derived class: one implicitly generated by the compiler and one inherited
> > from the base class?
>
> The argument types don't matter. A derived class function hides ALL base
> class functions of the same name, regardless of the function signature.
> That's the same rule as applies to any other function. You can use a
> using-declaration to bring in the base class function name.
The rule is stronger than that. Hiding is not based on whether something
is a function. Hiding is based on only on names. Any name in a scope
hides all instances of that name in all outer scopes.
--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: John Kewley <kewley@cscs.ch>
Date: Thu, 25 Jan 2001 17:16:11 GMT Raw View
James Kuyper wrote:
>
> ...
> No. I still don't know what's in foobar.h. In particular, I've no idea
> whether your code #includes the relevant standard headers, or not.
> Without the using-declaration that Victor Barazov mentioned, any use of
> "cout" without a "std::" prefix would access the global definition, not
> the one from namespace std. The global definition of "cout" doesn't even
> exist unless you give it one, and if it did exist, there's no guarantee
> that it's definition is in any way compatible with the definition of
> "std::cout". For all I know, "stdafx.h" might be a file which provides
> alternative global definitions of "cout" and "endl", and for an
> appropriate operator overload. In that case, your example code:
>
> cout << "BOO!!" << endl;
It could also define a namespace fred which contains a class std. It could
then
have a using statement to bring all of freds names into scope so that
std::cout << "BOO!!" << std::endl;
might not work as intended.
:-)
JK
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Thu, 18 Jan 2001 18:23:21 GMT Raw View
In article <t6cfoif6ue4ib9@corp.supernews.com>, Pete Kirman
<petekirman@hotmail.com> writes
>Can anybody tell me why the Standard says the operator = is non-inheritable
>ie why the following
>code doesn't compile:
This is the interaction of two rules
1) in any class where it is not explicitly declared the compiler will
(attempt) to generate a copy assignment. This means that the name
operator= is always found in any class scope.
2) Once a name is found in a scope, enclosing and base scopes are not
checked.
The way to deal with that problem is a using declaration
Try writing
using A::operator=;
in class B.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Pete Kirman" <petekirman@hotmail.com>
Date: Thu, 18 Jan 2001 22:00:31 GMT Raw View
But in this case I am not using an operator that is taking the same
arguments as the compiler generated method, so surely I'm using the
overloading capabilities of the language to provide two operators in the
derived class: one implicitly generated by the compiler and one inherited
from the base class?
> This is the interaction of two rules
>
> 1) in any class where it is not explicitly declared the compiler will
> (attempt) to generate a copy assignment. This means that the name
> operator= is always found in any class scope.
>
> 2) Once a name is found in a scope, enclosing and base scopes are not
> checked.
>
> The way to deal with that problem is a using declaration
>
> Try writing
>
> using A::operator=;
>
> in class B.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Risto Lankinen" <rlankine@hotmail.com>
Date: Thu, 18 Jan 2001 22:00:58 GMT Raw View
Hi!
Francis Glassborow <francis.glassborow@ntlworld.com> wrote in message
news:s6v+yIAe3pZ6Ewv$@ntlworld.com...
> This is the interaction of two rules
>
> 1) in any class where it is not explicitly declared the compiler will
> (attempt) to generate a copy assignment. This means that the name
> operator= is always found in any class scope.
>
> 2) Once a name is found in a scope, enclosing and base scopes are not
> checked.
Your explanation makes sense. However, the next question is
why, then, doesn't the program below print the expected output:
= = = = = =
#include "stdafx.h"
class Derived;
class Base
{
public:
Derived &operator=( const Derived & );
};
class Derived : public Base
{
};
Derived &Base::operator=( const Derived &r )
{
cout << "BOO!!" << endl;
return Derived(r);
}
int main( int,char *[] )
{
Derived a;
Derived b;
a = b;
return 0;
}
= = = = = =
The program should print "BOO!!". But when I compile it with
MSVC 6.0 the program outputs nothing, however, indicating
that the compiler-generated Derived::operator( Derived &) is
being called.
The Base class defines Derived &operator=(Derived &) [sic!] so
that it should be available for name resolution in the Derived class
without the compiler having to generate it. Why isn't it being used?
Thanks a lot in advance!
- Risto -
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Pete Kirman" <petekirman@hotmail.com>
Date: Fri, 19 Jan 2001 02:21:34 GMT Raw View
This is exactly what I'm saying!
The explicitly defined operator in class Base isn't used because the
implicitly (compiler) defined one in class Derived prevents the method being
inherited.
It's been pretty well shown that this is what happens as defined by the
Standard, but I want to know why the Standard defines this behaviour, it
seems counterintuitive to the idea of inheriting interface.
> Your explanation makes sense. However, the next question is
> why, then, doesn't the program below print the expected output:
>
> = = = = = =
>
> #include "stdafx.h"
>
> class Derived;
>
> class Base
> {
> public:
> Derived &operator=( const Derived & );
> };
>
> class Derived : public Base
> {
> };
>
> Derived &Base::operator=( const Derived &r )
> {
> cout << "BOO!!" << endl;
> return Derived(r);
> }
>
> int main( int,char *[] )
> {
> Derived a;
> Derived b;
>
> a = b;
>
> return 0;
> }
>
> = = = = = =
>
> The program should print "BOO!!". But when I compile it with
> MSVC 6.0 the program outputs nothing, however, indicating
> that the compiler-generated Derived::operator( Derived &) is
> being called.
>
> The Base class defines Derived &operator=(Derived &) [sic!] so
> that it should be available for name resolution in the Derived class
> without the compiler having to generate it. Why isn't it being used?
>
> Thanks a lot in advance!
>
> - Risto -
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Ron Natalie <ron@spamcop.net>
Date: Fri, 19 Jan 2001 04:27:20 GMT Raw View
>
> The Base class defines Derived &operator=(Derived &) [sic!] so
> that it should be available for name resolution in the Derived class
> without the compiler having to generate it. Why isn't it being used?
>
Nope, it doesn't care what you've defined in the base. A copy assignment
operator is implicitly generated if you don't provide one. That one
then hides the base one.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Victor Bazarov" <vAbazarov@dAnai.com>
Date: Fri, 19 Jan 2001 04:27:27 GMT Raw View
"Risto Lankinen" <rlankine@hotmail.com> wrote...
> Hi!
>
> Francis Glassborow <francis.glassborow@ntlworld.com> wrote in message
> news:s6v+yIAe3pZ6Ewv$@ntlworld.com...
> > This is the interaction of two rules
> >
> > 1) in any class where it is not explicitly declared the compiler
will
> > (attempt) to generate a copy assignment. This means that the name
> > operator= is always found in any class scope.
> >
> > 2) Once a name is found in a scope, enclosing and base scopes are
not
> > checked.
>
> Your explanation makes sense. However, the next question is
> why, then, doesn't the program below print the expected output:
>
> = = = = = =
>
> #include "stdafx.h"
Huh? Didn't you mean
#include <iostream>
using namespace std;
???
>
> class Derived;
>
> class Base
> {
> public:
> Derived &operator=( const Derived & );
> };
>
> class Derived : public Base
> {
> };
>
> Derived &Base::operator=( const Derived &r )
> {
> cout << "BOO!!" << endl;
> return Derived(r);
> }
>
> int main( int,char *[] )
> {
> Derived a;
> Derived b;
>
> a = b;
>
> return 0;
> }
>
> = = = = = =
>
> The program should print "BOO!!". But when I compile it with
Why _should_ it? You essentially did this:
#include <iostream>
using namespace std;
struct B {
int foo(int i) { cout << "BOO!" << endl; return i + 1; }
};
struct D : B {
int foo(int i) { return i - 1; }
};
int main()
{
D d;
d.foo(0);
}
So, why do you expect the program to call the BASE class method
when there is one in the DERIVED?
IMPORTANT (read carefully): There is ALWAYS an assignment operator
in the derived class. No matter what you do, there is one. Either
you declare/define it or the compiler will. There is NO WAY to
NOT HAVE it.
> MSVC 6.0 the program outputs nothing, however, indicating
> that the compiler-generated Derived::operator( Derived &) is
> being called.
That's right.
>
> The Base class defines Derived &operator=(Derived &) [sic!] so
> that it should be available for name resolution in the Derived class
^^^^^^
Again, why SHOULD it?
> without the compiler having to generate it. Why isn't it being used?
Have you heard of hiding? Overloading works ONLY IN THE SAME SCOPE.
It works with virtual functions because they exist in the scope that
spans the entire hierarchy tree (from the point of the first
declaration down). A new virtual function (in a derived class)
OVERLOADS the previously declared virtual function. However, it's
NOT the case with regular member functions. If there is one in
the derived class with the SAME NAME, the compiler won't see any
other function. It's not the first time you see it (I am sure)
#include <iostream>
using namespace std;
struct B {
void foo(int) { cout << "foo(int)" << endl; }
};
struct D : B {
void foo(const char*) { cout << "foo(const char*)" << endl; }
};
int main()
{
D d;
d.foo("whatever"); // fine
d.foo(12345); // error - cannot convert int to const char*
}
void D::foo(const char*) has HIDDEN the B::foo(int). Remove it
and D::foo(int) will be accessible because there will be nothing
HIDING it.
Now, if you add this line
using B::foo;
to the definition of D, you will be able to call d.foo(12345).
Check for yourself!
>
> Thanks a lot in advance!
You're welcome.
Victor
--
Please remove capital A's from my address when replying by mail
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Fri, 19 Jan 2001 19:40:01 GMT Raw View
In article <947rr5$mcm$1@nnrp.atgi.net>, Victor Bazarov
<vAbazarov@dAnai.com> writes
>Have you heard of hiding? Overloading works ONLY IN THE SAME SCOPE.
>It works with virtual functions because they exist in the scope that
>spans the entire hierarchy tree (from the point of the first
>declaration down). A new virtual function (in a derived class)
>OVERLOADS the previously declared virtual function. However, it's
>NOT the case with regular member functions. If there is one in
>the derived class with the SAME NAME, the compiler won't see any
>other function. It's not the first time you see it (I am sure)
It isn't true for virtual functions either, and thinking so is a common
cause of errors.
struct B {
virtual void fn(int){cout <<1;}
};
struct D : public B {
virtual void fn(long){cout << 2;}
};
int main (){
D d;
d.fn(1);
}
outputs '2'
because the fn in D hides that in B.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Fri, 19 Jan 2001 23:06:56 GMT Raw View
In article <t6eee0o66lvj2f@corp.supernews.com>, Pete Kirman
<petekirman@hotmail.com> writes
>But in this case I am not using an operator that is taking the same
>arguments as the compiler generated method, so surely I'm using the
>overloading capabilities of the language to provide two operators in the
>derived class: one implicitly generated by the compiler and one inherited
>from the base class?
Overloading does not work that way. The derived class operator= HIDES
the base class one unless you bring that into scope with a using
declaration.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Fri, 19 Jan 2001 23:15:11 GMT Raw View
In article <t6efs53fi16h44@corp.supernews.com>, Risto Lankinen
<rlankine@hotmail.com> writes
>The program should print "BOO!!". But when I compile it with
>MSVC 6.0 the program outputs nothing, however, indicating
>that the compiler-generated Derived::operator( Derived &) is
>being called.
>
>The Base class defines Derived &operator=(Derived &) [sic!] so
>that it should be available for name resolution in the Derived class
>without the compiler having to generate it. Why isn't it being used?
>
>Thanks a lot in advance!
Same reason, the compiler generated version for Derived ALWAYS hides ALL
versions in the base class. BTW, the signatures do not match because the
base class function you wrote assigns a Derived to a Base (the first
operand is always that of the class in which the declaration is made)
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Fri, 19 Jan 2001 23:15:25 GMT Raw View
In article <t6evjrkm87pgc3@corp.supernews.com>, Pete Kirman
<petekirman@hotmail.com> writes
>It's been pretty well shown that this is what happens as defined by the
>Standard, but I want to know why the Standard defines this behaviour, it
>seems counterintuitive to the idea of inheriting interface.
Why do you think that the functions called operator= should behave
differently from any other member functions? There is no reason to
provide a different rule in this case, and doing so would be very
counter-intuitive to all those of us who understand name lookup rules.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Steve Clamage <stephen.clamage@sun.com>
Date: Sat, 20 Jan 2001 12:05:46 GMT Raw View
Pete Kirman wrote:
>
> But in this case I am not using an operator that is taking the same
> arguments as the compiler generated method, so surely I'm using the
> overloading capabilities of the language to provide two operators in the
> derived class: one implicitly generated by the compiler and one inherited
> from the base class?
No, because overloading happens only within one scope. Functions
declared in different scopes do not overload one another. The
fundamental rule of scopes is that a name declared in an inner
scope hides all instances of that name in all outer scopes. The
scope of a base class is considered to surround the scope of a
derived class.
--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Risto Lankinen" <rlankine@hotmail.com>
Date: Sat, 20 Jan 2001 12:07:55 GMT Raw View
Hi!
Victor Bazarov <vAbazarov@dAnai.com> wrote in message
news:947rr5$mcm$1@nnrp.atgi.net...
> "Risto Lankinen" <rlankine@hotmail.com> wrote...
> >
> > #include "stdafx.h"
>
> Huh? Didn't you mean
>
> #include <iostream>
> using namespace std;
No, I meant
#include "stdafx.h"
At preprocessing time this line is replaced with the contents of the
file "stdafx.h" which in turn may contain the two lines you suggest.
I thought that any rational reader of an advanced C++ forum such
as this would understand my question even when only the essential
is presented.
> > The program should print "BOO!!". But when I compile it with
>
> Why _should_ it?
I'm sorry, Victor, for using such a strong word as "should" in such a
vague and inexact manner. I really meant to say "could intuitively be
expected to".
> You essentially did this:
>
> #include <iostream>
>
> using namespace std;
>
> struct B {
> int foo(int i) { cout << "BOO!" << endl; return i + 1; }
> };
>
> struct D : B {
> int foo(int i) { return i - 1; }
> };
I was replying to a the following posting by Francis Glassborough:
| This is the interaction of two rules
|
| 1) in any class where it is not explicitly declared the compiler will
| (attempt) to generate a copy assignment. This means that the name
| operator= is always found in any class scope.
|
| 2) Once a name is found in a scope, enclosing and base scopes are not
| checked.
>From rule 1 it was not clear to me that a signature is _not_ defined
explicitly if it is inherited.
> So, why do you expect the program to call the BASE class method
> when there is one in the DERIVED?
Because the Base method _can_be_ the one that is in Derived.
> IMPORTANT (read carefully): There is ALWAYS an assignment operator
> in the derived class. No matter what you do, there is one. Either
> you declare/define it or the compiler will. There is NO WAY to
> NOT HAVE it.
See above.
> > The Base class defines Derived &operator=(Derived &) [sic!] so
> > that it should be available for name resolution in the Derived class
> ^^^^^^
> Again, why SHOULD it?
See further above.
> > without the compiler having to generate it. Why isn't it being used?
>
> Have you heard of hiding?
[ important educational lecture deleted ]
> It's not the first time you see it (I am sure)
I should have known. Thanks a lot for telling, you're the best!
Cheers!
- Risto -
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Pete Kirman" <petekirman@hotmail.com>
Date: Sat, 20 Jan 2001 12:08:58 GMT Raw View
I'm certainly not saying that there should be a different rule for operator=
(and I never did say that), I'm asking - why this is the case in general,
for a function called operator=, for a function called Foo, whatever, to me
it seems counter-intuitive ... blah blah see previous post.
I assumed that there was some underlying reason for this rule, but all I
seem to have got thus far is that "this is the case, because it says so in
the standard", which IMO is pretty weak.
> Why do you think that the functions called operator= should behave
> differently from any other member functions? There is no reason to
> provide a different rule in this case, and doing so would be very
> counter-intuitive to all those of us who understand name lookup rules.
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: James Kuyper <kuyper@wizard.net>
Date: Sun, 21 Jan 2001 00:03:34 GMT Raw View
Pete Kirman wrote:
>
> I'm certainly not saying that there should be a different rule for operator=
> (and I never did say that), I'm asking - why this is the case in general,
> for a function called operator=, for a function called Foo, whatever, to me
> it seems counter-intuitive ... blah blah see previous post.
> I assumed that there was some underlying reason for this rule, but all I
> seem to have got thus far is that "this is the case, because it says so in
> the standard", which IMO is pretty weak.
The relevant rule is the one that says that a derived class function
hides all base class functions of the same name, regardless of the
function signature, a rule that applies to all functions, not just
operator=(). This rule was written to make overloading behavior more
predictable. You're can always make the base class names visible with a
using-declaration. Here's the bext example I've found on Deja showing
why the rule is needed:
> From: Jim Hyslop <jim.hyslop@leitch.com>
> Subject: Re: Problem with virtual & overloaded functions
> Date: 18 Apr 2000 00:00:00 GMT
...
> "Sebastian Moleski" <sebmol@gmx.net> wrote:
> > So the next question would be: why? What
> > is the rationale behind forbidding such
> > design and requiring use of the "using"
> > statement/directive (whatever the
> > appropriate naming is)?
> To prevent sudden, unexpected changes in behaviour if you add an overloaded function. For example:
>
> class base
> {
> public:
> };
>
> class derived : public base
> {
> public:
> void f(double);
> };
>
> int main()
> {
> derived d;
> d.f(0);
> }
>
> The compiler will happily accept this program, and implicitly convert the int to a double. Without the rule in question, if you add a function 'f(int)' to base, you would
> suddenly change how the derived class behaves - leading to all sorts of debugging headaches.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Sun, 21 Jan 2001 00:03:38 GMT Raw View
In article <t6hn8385voa1ce@corp.supernews.com>, Pete Kirman
<petekirman@hotmail.com> writes
>I'm certainly not saying that there should be a different rule for operator=
>(and I never did say that), I'm asking - why this is the case in general,
>for a function called operator=, for a function called Foo, whatever, to me
>it seems counter-intuitive ... blah blah see previous post.
>I assumed that there was some underlying reason for this rule, but all I
>seem to have got thus far is that "this is the case, because it says so in
>the standard", which IMO is pretty weak.
There is a perfectly good answer to the question you did not originally
ask. When I look at the interface of a class and see a specific name I
know that I do not need to look into outer scopes. What I see is what I
get. If, as a class designer, I want more I must say so with a using
declaration and thereby alert my client to the fact that there are other
declarations that will be considered by the compiler.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Victor Bazarov" <vAbazarov@dAnai.com>
Date: Sun, 21 Jan 2001 06:05:21 GMT Raw View
"Risto Lankinen" <rlankine@hotmail.com> wrote...
> Hi!
>
> [...]
> > You essentially did this:
> >
> > #include <iostream>
> >
> > using namespace std;
> >
> > struct B {
> > int foo(int i) { cout << "BOO!" << endl; return i + 1; }
> > };
> >
> > struct D : B {
> > int foo(int i) { return i - 1; }
> > };
>
> I was replying to a the following posting by Francis Glassborough:
>
> | This is the interaction of two rules
> |
> | 1) in any class where it is not explicitly declared the compiler will
> | (attempt) to generate a copy assignment. This means that the name
> | operator= is always found in any class scope.
> |
> | 2) Once a name is found in a scope, enclosing and base scopes are not
> | checked.
>
> >From rule 1 it was not clear to me that a signature is _not_ defined
> explicitly if it is inherited.
The signature has NOTHING to do with it. The "(attempt)" part
is because there can be data members that will not permit the
generation of the assignment operator (like references, e.g.).
In that case the compilator will fail. If the attempt is not
UNsuccessful, then, as I said before, the generated assignment
operator will ALWAYS exist in your derived class, either declared
by you or generated by compiler. BUT NEVER the one from the base
class[es].
>
> > So, why do you expect the program to call the BASE class method
> > when there is one in the DERIVED?
>
> Because the Base method _can_be_ the one that is in Derived.
No, it can't. Not in case of the assignment operator. The case
where it CAN be the one if that is NOT AN ASSIGNMENT OP. That's
the exception that the operator= carries. It simply HAS TO EXIST
for every class (and that's why it's generated if you don't do it
yourself, like the default constructor). That's why the assignment
operator is included into the [pretty small] set of SPECIAL
functions.
Victor
--
Please remove capital A's from my address when replying by mail
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Risto Lankinen" <rlankine@hotmail.com>
Date: Mon, 22 Jan 2001 19:10:24 GMT Raw View
Hi!
Francis Glassborow <francis.glassborow@ntlworld.com> wrote in message
news:GnFkViA5XEa6Ewiz@ntlworld.com...
> BTW, the signatures do not match because the
> base class function you wrote assigns a Derived to a Base (the first
> operand is always that of the class in which the declaration is made)
This is an excellent point, which also lets me fully understand the
reason why the operator=() is always hidden. The explanation is
worth expanding a little bit:
The operator=() signatures with same arguments in two different
classes are seemingly identical. But think of other operators and
you'll realize that, for instance, operator-() can be defined in two
different ways:
* OutType SomeType::operator-( InType );
* OutType operator-( SomeType,InType );
>From there it is easy to see that operators which are defined inside
a class have an extra implicit argument whose type is the enclosing
class.
Now, if operator=() is defined inside class Base, it's _hypothetical_
out-of-class signature would be...
* Derived operator=( Base,Derived );
... which is not the same as if it was declared in the class Derived:
* Derived operator=( Derived,Derived );
.. and therefore does _not_ match with _any_ operator=() that is
defined (explicitly or implicitly) inside the class Derived.
Neat explanation! Thanks a lot!
- Risto -
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Risto Lankinen" <rlankine@hotmail.com>
Date: Mon, 22 Jan 2001 19:11:36 GMT Raw View
Hi!
Victor Bazarov <vAbazarov@dAnai.com> wrote in message
news:947rr5$mcm$1@nnrp.atgi.net...
> A new virtual function (in a derived class)
> OVERLOADS the previously declared virtual function.
Overrides, actually. There's a well-defined distinction between
the meanings of the two terms.
Cheers!
- Risto -
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: James Kuyper <kuyper@wizard.net>
Date: Mon, 22 Jan 2001 19:12:16 GMT Raw View
Pete Kirman wrote:
>
> But in this case I am not using an operator that is taking the same
> arguments as the compiler generated method, so surely I'm using the
> overloading capabilities of the language to provide two operators in the
> derived class: one implicitly generated by the compiler and one inherited
> from the base class?
The argument types don't matter. A derived class function hides ALL base
class functions of the same name, regardless of the function signature.
That's the same rule as applies to any other function. You can use a
using-declaration to bring in the base class function name.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: James Kuyper <kuyper@wizard.net>
Date: Mon, 22 Jan 2001 19:12:56 GMT Raw View
Risto Lankinen wrote:
>
> Hi!
>
> Victor Bazarov <vAbazarov@dAnai.com> wrote in message
> news:947rr5$mcm$1@nnrp.atgi.net...
> > "Risto Lankinen" <rlankine@hotmail.com> wrote...
> > >
> > > #include "stdafx.h"
> >
> > Huh? Didn't you mean
> >
> > #include <iostream>
> > using namespace std;
>
> No, I meant
>
> #include "stdafx.h"
>
> At preprocessing time this line is replaced with the contents of the
> file "stdafx.h" which in turn may contain the two lines you suggest.
There's nothing in the standard which guarantees that. Any reader who's
not used MSVC++ is unlikely to have any idea what "stdafx.h" contains.
> I thought that any rational reader of an advanced C++ forum such
> as this would understand my question even when only the essential
> is presented.
Yes, "the essentials" are the two lines that Victor Barazov wrote; the
one line that you wrote was inappropriate for a standards-related
question on this newsgroup. To the extent possible, example code posted
to this newsgroup should avoid implementation-specific items, except
when the question is about whether the implementation-specific stuff is
compatible with the standard.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Risto Lankinen" <rlankine@hotmail.com>
Date: Mon, 22 Jan 2001 20:45:13 GMT Raw View
Hi!
James Kuyper <kuyper@wizard.net> wrote in message
news:3A69BBE9.7FF87336@wizard.net...
> Risto Lankinen wrote:
> >
> > #include "stdafx.h"
> >
> > At preprocessing time this line is replaced with the contents of the
> > file "stdafx.h" which in turn may contain the two lines [Victor]
suggest[s].
>
> There's nothing in the standard which guarantees that.
Huh? I've been using this syntax for header inclusion and it
works just fine. How should I include my own headers if I
want to follow the standard?
> Any reader who's
> not used MSVC++ is unlikely to have any idea what "stdafx.h" contains.
Would you have been satisfied had I used "foobar.h" instead?
If yes, then please imagine that I did so, so that we can forget
about this deviation from the original topic.
Anyway, what's MSVC got to do with this? Please correct
if I'm wrong, but surely C++ standard doesn't limit the use of
the file name "stdafx.h" to just one compiler or OS vendor?
Cheers!
- Risto -
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: James Kuyper <kuyper@wizard.net>
Date: Tue, 23 Jan 2001 15:10:10 GMT Raw View
Risto Lankinen wrote:
>
> Hi!
>
> James Kuyper <kuyper@wizard.net> wrote in message
> news:3A69BBE9.7FF87336@wizard.net...
> > Risto Lankinen wrote:
> > >
> > > #include "stdafx.h"
> > >
> > > At preprocessing time this line is replaced with the contents of the
> > > file "stdafx.h" which in turn may contain the two lines [Victor]
> suggest[s].
> >
> > There's nothing in the standard which guarantees that.
>
> Huh? I've been using this syntax for header inclusion and it
> works just fine. How should I include my own headers if I
> want to follow the standard?
That's precisely the correct syntax, but the consequences of using that
syntax are implementation defined, and EXTREMELY context dependent.
> > Any reader who's
> > not used MSVC++ is unlikely to have any idea what "stdafx.h" contains.
>
> Would you have been satisfied had I used "foobar.h" instead?
No. I still don't know what's in foobar.h. In particular, I've no idea
whether your code #includes the relevant standard headers, or not.
Without the using-declaration that Victor Barazov mentioned, any use of
"cout" without a "std::" prefix would access the global definition, not
the one from namespace std. The global definition of "cout" doesn't even
exist unless you give it one, and if it did exist, there's no guarantee
that it's definition is in any way compatible with the definition of
"std::cout". For all I know, "stdafx.h" might be a file which provides
alternative global definitions of "cout" and "endl", and for an
appropriate operator overload. In that case, your example code:
cout << "BOO!!" << endl;
could have just about any effect you want it to have. "stdafx.h" could
contain #defines of "Derived", "Base", "r", "a", or "b", rendering the
behavior of your example code impossible to deduce from it's text alone.
Either you're expecting us to recognise and understand a vendor-specific
file naming convention, which is inappropriate for message posted to a
standards-related newsgroup, or you're expecting us to treat "stdafx" as
a complete unknown, in which case the behavior of your example code is
equally unknown.
> If yes, then please imagine that I did so, so that we can forget
> about this deviation from the original topic.
>
> Anyway, what's MSVC got to do with this? Please correct
> if I'm wrong, but surely C++ standard doesn't limit the use of
> the file name "stdafx.h" to just one compiler or OS vendor?
No - that's precisely the point. Since "stdafx.h" is NOT one of the
standard headers, there's no way for us to guess what it contains. For
purposes of postings to this newsgroup, you should either "promote" the
relevant lines up from the header file into the source code, or at least
quote them from the header file.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Pete Kirman" <petekirman@hotmail.com>
Date: Thu, 18 Jan 2001 01:29:56 GMT Raw View
Can anybody tell me why the Standard says the operator = is non-inheritable
ie why the following
code doesn't compile:
Thanks in advance ...
class Foo
{
public:
Foo(){};
Foo& operator =(int i)
{
iVal = i;
return *this;
};
protected:
int iVal;
};
class Boo : public Foo
{
public:
Boo(){};
};
int main(int argc, char* argv[])
{
Boo b;
b = 1;
return 0;
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Richard Andrews" <richarda@ixla.com.au>
Date: Thu, 18 Jan 2001 17:16:51 GMT Raw View
In article <t6cfoif6ue4ib9@corp.supernews.com>, "Pete Kirman"
<petekirman@hotmail.com> wrote:
> Can anybody tell me why the Standard says the operator = is
> non-inheritable ie why the following code doesn't compile:
>
> Thanks in advance ...
>
> class Foo
> {
> public:
> Foo(){}; Foo& operator =(int i)
> {
> iVal = i; return *this;
> };
>
> protected:
> int iVal;
> };
>
> class Boo : public Foo
> {
> public:
> Boo(){};
> };
>
> int main(int argc, char* argv[])
> {
> Boo b; b = 1; return 0;
> }
>
Here's my take on the situation (but I'm not on the committee so I can't
know for sure).
operator= is analogous to a constructor in this situation in the sense
that there's no point using the constructor method of a parent class to
construct a child class. It would only construct as much of the object as
the parent knows about. You wouldn't get any specialization.
The same goes for operator=. There's no point using the assignment of a
parent class as it can only do a partial assignment. It is also essential
that operator= performs every level of assignment from the most derived to
the most general so Derived::operator=() must call BaseClass::operator=()
which in turn must call its base class operator=() etc.
This is again analogous to a constructor which must call other
constructors of its parent classes. This is generally hidden from the
programmer because if you don't specify any special constructor then the
default constructor is chosen, but it still must be done.
In short, inheriting operator= would be misleading because its behaviour
would not be as expected. The standard tries to prevent misleading code
from being created.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]