home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / lang / cplus / 17893 < prev    next >
Encoding:
Text File  |  1992-12-13  |  3.4 KB  |  114 lines

  1. Newsgroups: comp.lang.c++
  2. Path: sparky!uunet!taumet!steve
  3. From: steve@taumet.com (Steve Clamage)
  4. Subject: Re: Who is wrong? me, BC , G
  5. Message-ID: <1992Dec13.165726.19251@taumet.com>
  6. Organization: TauMetric Corporation
  7. References: <7249.1635.uupcb@factory.com>
  8. Date: Sun, 13 Dec 1992 16:57:26 GMT
  9. Lines: 103
  10.  
  11. chris.sokol@factory.com (Chris Sokol)  writes:
  12.  
  13. |48ganelin@cua.edu writes:
  14.  
  15. |>class A
  16. |>{
  17. |>public:
  18. |>  A & operator += ( const A & x ) ;
  19. |>};
  20.  
  21. |>class B : public A
  22. |>{
  23. |>public:
  24. |>  B & operator += ( const int x ) ;
  25. |>};
  26.  
  27. |>void main ()
  28. |>{
  29. |> B  x , y ;
  30. |> x += y ;            //  BorlandC complains here !!!!
  31. |>}
  32.  
  33. |>WHY !!!!!
  34.  
  35. |If you wish to use a method of class B which has been derived from class A by
  36. |name, several dos compilers (BC/Zortech) complain if the overloading function
  37. |does not take the same number/type of parameters.
  38.  
  39. This is not the explanation.  We are not looking at compiler dependencies,
  40. but at a fundamental language rule.  If g++ compiles this code, it is
  41. wrong.  Perhaps a later version would report the error.
  42.  
  43. Let's consider the basic scoping rule in C, C++, and many other languages:
  44.  
  45. An identifier in a scope hides all instances of that identifier in all
  46. outer scopes.  For example:
  47.  
  48.     void f();
  49.     int g()
  50.     {
  51.         int f = 1;
  52.         f();    // illegal, 'f()' is hidden
  53.         {
  54.         double f = 2.0;
  55.         if( ... )
  56.             return f;    // returns (int)2.0, since 'int f' is hidden
  57.         }
  58.         return f;        // returns 1
  59.     }
  60.  
  61. Overloading in C++ applies only within the same scope because of this 
  62. fundamental rule.  Example:
  63.  
  64.     void f(int);
  65.     void g()
  66.     {
  67.         void f(double);    //hides 'f(int)'
  68.         f(1);        // calls f((double)1), the only visible f()
  69.     }
  70.  
  71. This, by the way, is why you don't want to declare functions anywhere
  72. but file (or class) scope.
  73.  
  74. A derived class does not have the same scope as a base class, so no
  75. function in a derived class can overload any function in a base class.
  76. This is true for virtual functions as well, a point that is sometimes
  77. missed.  "Virtual" is a concept independent of "overloading" and
  78. only loosely tied to scope.
  79.  
  80. In the specific example, function B::operator+=() hides A::operator+=().
  81. There is no visible += which can be applied to 2 objects of type B, and
  82. the code is in error.  There are basically three ways to proceed:
  83.  
  84. 1.  (not recommended) Use scope overriding to call the base-class function:
  85.     x.A::operator+=(y)
  86.     The compiler will quietly cast the B objects and apply the operator
  87.     to their A portions.
  88.  
  89. 2.  (not recommended) Cast the objects yourself:
  90.     (A&)x += (A&)y    // exactly the same effect as #1
  91.  
  92. 3.  (recommended) Supply the appropriate operator in class B:
  93.     inline B& B::operator+=(const B& b) {
  94.         ((A*)this)->operator+=(b);
  95.         return *this;
  96.         }
  97.     This will ensure the proper overloading in class B.  It will also
  98.     ensure the right operations if B should change so that += has more
  99.     to do.  For example, if a data member is added to B, one would expect
  100.     it to take part in assignment.  You would add an operator+=() then,
  101.     but the existing code in examples 1 and 2 would still call the
  102.     base-class version, a subtle bug.  If you define your own
  103.     operator+= now, only it need change when the class changes.
  104.  
  105.     You might want to supply
  106.     inline B& B::operator+=(const A& a)
  107.         ((A*)this)->operator+=(a);
  108.         return *this;
  109.         }
  110.     instead, or in addition, depending on the nature of the classes.
  111. -- 
  112.  
  113. Steve Clamage, TauMetric Corp, steve@taumet.com
  114.