home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: sparky!uunet!taumet!steve
- From: steve@taumet.com (Steve Clamage)
- Subject: Re: Who is wrong? me, BC , G
- Message-ID: <1992Dec13.165726.19251@taumet.com>
- Organization: TauMetric Corporation
- References: <7249.1635.uupcb@factory.com>
- Date: Sun, 13 Dec 1992 16:57:26 GMT
- Lines: 103
-
- chris.sokol@factory.com (Chris Sokol) writes:
-
- |48ganelin@cua.edu writes:
-
- |>class A
- |>{
- |>public:
- |> A & operator += ( const A & x ) ;
- |>};
-
- |>class B : public A
- |>{
- |>public:
- |> B & operator += ( const int x ) ;
- |>};
-
- |>void main ()
- |>{
- |> B x , y ;
- |> x += y ; // BorlandC complains here !!!!
- |>}
-
- |>WHY !!!!!
-
- |If you wish to use a method of class B which has been derived from class A by
- |name, several dos compilers (BC/Zortech) complain if the overloading function
- |does not take the same number/type of parameters.
-
- This is not the explanation. We are not looking at compiler dependencies,
- but at a fundamental language rule. If g++ compiles this code, it is
- wrong. Perhaps a later version would report the error.
-
- Let's consider the basic scoping rule in C, C++, and many other languages:
-
- An identifier in a scope hides all instances of that identifier in all
- outer scopes. For example:
-
- void f();
- int g()
- {
- int f = 1;
- f(); // illegal, 'f()' is hidden
- {
- double f = 2.0;
- if( ... )
- return f; // returns (int)2.0, since 'int f' is hidden
- }
- return f; // returns 1
- }
-
- Overloading in C++ applies only within the same scope because of this
- fundamental rule. Example:
-
- void f(int);
- void g()
- {
- void f(double); //hides 'f(int)'
- f(1); // calls f((double)1), the only visible f()
- }
-
- This, by the way, is why you don't want to declare functions anywhere
- but file (or class) scope.
-
- A derived class does not have the same scope as a base class, so no
- function in a derived class can overload any function in a base class.
- This is true for virtual functions as well, a point that is sometimes
- missed. "Virtual" is a concept independent of "overloading" and
- only loosely tied to scope.
-
- In the specific example, function B::operator+=() hides A::operator+=().
- There is no visible += which can be applied to 2 objects of type B, and
- the code is in error. There are basically three ways to proceed:
-
- 1. (not recommended) Use scope overriding to call the base-class function:
- x.A::operator+=(y)
- The compiler will quietly cast the B objects and apply the operator
- to their A portions.
-
- 2. (not recommended) Cast the objects yourself:
- (A&)x += (A&)y // exactly the same effect as #1
-
- 3. (recommended) Supply the appropriate operator in class B:
- inline B& B::operator+=(const B& b) {
- ((A*)this)->operator+=(b);
- return *this;
- }
- This will ensure the proper overloading in class B. It will also
- ensure the right operations if B should change so that += has more
- to do. For example, if a data member is added to B, one would expect
- it to take part in assignment. You would add an operator+=() then,
- but the existing code in examples 1 and 2 would still call the
- base-class version, a subtle bug. If you define your own
- operator+= now, only it need change when the class changes.
-
- You might want to supply
- inline B& B::operator+=(const A& a)
- ((A*)this)->operator+=(a);
- return *this;
- }
- instead, or in addition, depending on the nature of the classes.
- --
-
- Steve Clamage, TauMetric Corp, steve@taumet.com
-