home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!think.com!ames!agate!forney.berkeley.edu!jbuck
- From: jbuck@forney.berkeley.edu (Joe Buck)
- Newsgroups: gnu.g++.help
- Subject: Re: what is a "contravarience violation for method types"
- Date: 23 Nov 1992 20:06:42 GMT
- Organization: U. C. Berkeley
- Lines: 110
- Distribution: world
- Message-ID: <1erdkiINN89p@agate.berkeley.edu>
- References: <SETHG.92Nov23113233@roar.CS.Berkeley.EDU>
- NNTP-Posting-Host: forney.berkeley.edu
-
- In article <SETHG.92Nov23113233@roar.CS.Berkeley.EDU> sethg@roar.CS.Berkeley.EDU (Seth C. Goldstein) writes:
- >When compiling the following with g++-2.3.1 I get warnings of the form:
- >
- >quad.C: In method `Toplevel::Toplevel ()':
- >quad.C:27: warning: contravariance violation for method types ignored
- >
- >What does it mean?
- >
- >example:
- >////////////////////////////////////////////////////////////////////////
- >class Frame;
- >typedef void (Frame::*Codeblock)(void);
- >
- >class Frame
- >{
- >protected:
- > int counter;
- >
- >public:
- > inline Frame(Codeblock function);
- >};
- >
- >class Toplevel : Frame
- >{
- > int i;
- >public:
- > Toplevel(void);
- > void runtop(void);
- >};
- >
- >Toplevel::Toplevel(void) : Frame(&(Toplevel::runtop)) // line 27
- >{
- >
- >}
-
- This is a horribly phrased error message, but I don't know of a short
- way to describe the problem. You are using a pointer to a Toplevel
- member function where a pointer to a Frame function is desired. This
- is a no-no. Here's why: assume the code were written this way:
-
- typedef void (Frame::*Codeblock)(void);
-
- class Frame {
- Codeblock funcP;
- public:
- Frame(Codeblock function);
- void doItTo(Frame&);
- };
-
- class Toplevel : Frame
- {
- int i;
- public:
- Toplevel(void);
- void runtop(void);
- };
-
- Toplevel::Toplevel(void) : Frame(&(Toplevel::runtop)) {}
-
- void Toplevel::runTop() { i = 1;}
-
- // Now here's where the problem comes from:
-
- void Frame::doItTo(Frame& arg) {
- arg.funcP();
- }
-
- Note that arg can be any Frame object, not necessarily a TopLevel.
- Now consider the following code:
-
- TopLevel foo;
- Frame bar;
- foo.doItTo(bar);
-
- We will now attempt to set bar's "i" member to 1 -- but bar has no
- i member because it is not a TopLevel. Result: a crash, or who knows
- what.
-
- Pointers to member functions "inherit backwards", hence the word
- "contravariant" among the compiler folks. Given
-
- class Base...
-
- class Derived: public Base...
-
- typedef void (Base::*VoidBaseFuncP)(void);
- typedef void (Derived::*VoidDerivedFuncP)(void);
-
- then it is legal to assign a VoidBaseFuncP to a VoidDerivedFuncP without
- a cast, but not vice versa. This is exactly the reverse of the behavior
- for pointers to objects, where it is legal to assign a Derived* pointer
- to a Base* pointer without a cast, but not vice versa.
-
- Now in your case, you may be able to assure that the TopLevel function
- will never be called on a non-TopLevel object through the pointer (perhaps
- because functions like doItTo are not present and the function is only
- applied to the object itself). In that case, use a cast to make the
- warning disappear, but remember that casts tell the compiler "Don't bother
- me, I know what I am doing", so make sure you are!
-
- I would ask the g++ maintainers to consider rephrasing the error message
- to something like
-
- warning: unsafe to assign pointer to member of derived class (class YYY)
- to pointer to member of base (class XXX)
-
- though I am not sure that this phrasing covers all the situations in which
- the present message can be issued.
- --
- Joe Buck jbuck@ohm.berkeley.edu
-