Article View: gnu.g++.help
Article #604Re: what is a "contravarience violation for method types"
From: Joe Buck
Date: Mon, 23 Nov 1992 20:06
Date: Mon, 23 Nov 1992 20:06
110 lines
3633 bytes
3633 bytes
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
Technical Details
Message-ID:
<1erdkiINN89p@agate.berkeley.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!think.com!ames!agate!forney.berkeley.edu!jbuckReferences:
<SETHG.92Nov23113233@roar.CS.Berkeley.EDU>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!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