home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / gnu / g / help / 1477 < prev    next >
Encoding:
Text File  |  1992-11-23  |  3.4 KB  |  123 lines

  1. Path: sparky!uunet!think.com!ames!agate!forney.berkeley.edu!jbuck
  2. From: jbuck@forney.berkeley.edu (Joe Buck)
  3. Newsgroups: gnu.g++.help
  4. Subject: Re: what is a "contravarience violation for method types"
  5. Date: 23 Nov 1992 20:06:42 GMT
  6. Organization: U. C. Berkeley
  7. Lines: 110
  8. Distribution: world
  9. Message-ID: <1erdkiINN89p@agate.berkeley.edu>
  10. References: <SETHG.92Nov23113233@roar.CS.Berkeley.EDU>
  11. NNTP-Posting-Host: forney.berkeley.edu
  12.  
  13. In article <SETHG.92Nov23113233@roar.CS.Berkeley.EDU> sethg@roar.CS.Berkeley.EDU (Seth C. Goldstein) writes:
  14. >When compiling the following with g++-2.3.1 I get warnings of the form:
  15. >
  16. >quad.C: In method `Toplevel::Toplevel ()':
  17. >quad.C:27: warning: contravariance violation for method types ignored
  18. >
  19. >What does it mean?
  20. >
  21. >example:
  22. >////////////////////////////////////////////////////////////////////////
  23. >class Frame;
  24. >typedef void (Frame::*Codeblock)(void);
  25. >
  26. >class Frame
  27. >{
  28. >protected:
  29. >    int         counter;
  30. >
  31. >public:
  32. >    inline      Frame(Codeblock function);
  33. >};
  34. >
  35. >class Toplevel : Frame
  36. >{
  37. >    int         i;
  38. >public:
  39. >                Toplevel(void);
  40. >    void        runtop(void);
  41. >};
  42. >
  43. >Toplevel::Toplevel(void) : Frame(&(Toplevel::runtop))    // line 27
  44. >{
  45. >
  46. >}
  47.  
  48. This is a horribly phrased error message, but I don't know of a short
  49. way to describe the problem.  You are using a pointer to a Toplevel
  50. member function where a pointer to a Frame function is desired.  This
  51. is a no-no.  Here's why: assume the code were written this way:
  52.  
  53. typedef void (Frame::*Codeblock)(void);
  54.  
  55. class Frame {
  56.     Codeblock funcP;
  57. public:
  58.     Frame(Codeblock function);
  59.     void doItTo(Frame&);
  60. };
  61.  
  62. class Toplevel : Frame
  63. {
  64.     int         i;
  65. public:
  66.                 Toplevel(void);
  67.     void        runtop(void);
  68. };
  69.  
  70. Toplevel::Toplevel(void) : Frame(&(Toplevel::runtop)) {}
  71.  
  72. void Toplevel::runTop() { i = 1;}
  73.  
  74. // Now here's where the problem comes from:
  75.  
  76. void Frame::doItTo(Frame& arg) {
  77.     arg.funcP();
  78. }
  79.  
  80. Note that arg can be any Frame object, not necessarily a TopLevel.
  81. Now consider the following code:
  82.  
  83.     TopLevel foo;
  84.     Frame bar;
  85.     foo.doItTo(bar);
  86.  
  87. We will now attempt to set bar's "i" member to 1 -- but bar has no
  88. i member because it is not a TopLevel.  Result: a crash, or who knows
  89. what.
  90.  
  91. Pointers to member functions "inherit backwards", hence the word
  92. "contravariant" among the compiler folks.  Given
  93.  
  94. class Base...
  95.  
  96. class Derived: public Base...
  97.  
  98. typedef void (Base::*VoidBaseFuncP)(void);
  99. typedef void (Derived::*VoidDerivedFuncP)(void);
  100.  
  101. then it is legal to assign a VoidBaseFuncP to a VoidDerivedFuncP without
  102. a cast, but not vice versa.  This is exactly the reverse of the behavior
  103. for pointers to objects, where it is legal to assign a Derived* pointer
  104. to a Base* pointer without a cast, but not vice versa.
  105.  
  106. Now in your case, you may be able to assure that the TopLevel function
  107. will never be called on a non-TopLevel object through the pointer (perhaps
  108. because functions like doItTo are not present and the function is only
  109. applied to the object itself).  In that case, use a cast to make the
  110. warning disappear, but remember that casts tell the compiler "Don't bother
  111. me, I know what I am doing", so make sure you are!
  112.  
  113. I would ask the g++ maintainers to consider rephrasing the error message
  114. to something like
  115.  
  116. warning: unsafe to assign pointer to member of derived class (class YYY)
  117. to pointer to member of base (class XXX)
  118.  
  119. though I am not sure that this phrasing covers all the situations in which
  120. the present message can be issued.
  121. --
  122. Joe Buck    jbuck@ohm.berkeley.edu
  123.