Topic: Q: Should the compiler warn for pure virtual methods calls within constructor?


Author: "Thomas R. Schar" <thomas.schar@dsto.defence.gov.au>
Date: 1998/05/25
Raw View
Hi All,

I had a problem with some code that I wrote, and after I solved
the problem, I thought the compiler should have issued some sort of
warning.  However, I will agree it was a silly mistake.

class X{
 public:
    X(){foo();}
    virtual void foo()=0;
};
class Y:public X{
 public:
    virtual void foo(){cout<<"Y::foo()\n";}
};
int main(){
    Y y;
    y.foo();
}

yielded a runtime error with "pure virtual method invoked".
Should the compiler have warned about this?

Well, I guess my first question is,
    (a) are virtual methods within a constructor statically resolved, or
         are they still accessed via the vtableptr?
    (b) if via the vtableptr, then it's understandable.
    (c) if it is statically resolved, then why doesn't it warn you??
         it must know it is pure virtual?

Interestingly enough, gcc/g++ 2.8.0 came up with a compilation error.
VC++5.0 came up with a link error.
Both CC4.1, and Borland C++5.02 compiled and linked fine, but came up
with a runtime error.

So who is correct?  (or more correct?)

Thanks for any responses.
Thomas.



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stephen.clamage@sun.com (Steve Clamage)
Date: 1998/05/25
Raw View
"Thomas R. Schar" <thomas.schar@dsto.defence.gov.au> writes:

>class X{
> public:
>    X(){foo();}
>    virtual void foo()=0;
>};
>class Y:public X{
> public:
>    virtual void foo(){cout<<"Y::foo()\n";}
>};
>int main(){
>    Y y;
>    y.foo();
>}
>
>yielded a runtime error with "pure virtual method invoked".
>Should the compiler have warned about this?
>
>Well, I guess my first question is,
>    (a) are virtual methods within a constructor statically resolved, or
>         are they still accessed via the vtableptr?
>    (b) if via the vtableptr, then it's understandable.

While a constructor is running, the type of the object is the
type of the constructor's own class. Functions belonging to
derived classes cannot be accessed unless you provide an
explicit qualifier. So from an X constructor, or from any
function it calls, any reference to an unqualified "foo" can
only be the pure vitual foo.

A pure virtual function can be defined (i.e. given a body),
but you can call it only with a qualifier, e.g. "X::foo()".
The virtual call mechanism never resolves to a pure virtual
function function.

>    (c) if it is statically resolved, then why doesn't it warn you??
>         it must know it is pure virtual?

The result of attempting to call a pure virtual function via the
virtual call mechanism is undefined, so the compiler is not
required to issue a warning. Consider it a "quality of
implementation" issue.

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: jkanze@otelo.ibmmail.com
Date: 1998/05/26
Raw View
In article <6kau40$63m$1@fang.dsto.defence.gov.au>,
  "Thomas R. Schar" <thomas.schar@dsto.defence.gov.au> wrote:
>
> Hi All,
>
> I had a problem with some code that I wrote, and after I solved
> the problem, I thought the compiler should have issued some sort of
> warning.  However, I will agree it was a silly mistake.
>
> class X{
>  public:
>     X(){foo();}
>     virtual void foo()=3D0;
> };
> class Y:public X{
>  public:
>     virtual void foo(){cout<<"Y::foo()\n";}
> };
> int main(){
>     Y y;
>     y.foo();
> }
>
> yielded a runtime error with "pure virtual method invoked".
> Should the compiler have warned about this?
>
> Well, I guess my first question is,
>     (a) are virtual methods within a constructor statically resolved, o=
r
>          are they still accessed via the vtableptr?

In theory, they are still resolved virtually (according to the dynamic
type).  However, during construction, the dynamic type is the type
of the constructor which is running; for code within the constructor
itself (but not necessarily in functions called by the constructor),
the compiler knows the dynamic type and can optimize out the dynamic
mechanism.

>     (b) if via the vtableptr, then it's understandable.
>     (c) if it is statically resolved, then why doesn't it warn you??
>          it must know it is pure virtual?

Well, this is comp.std.c++, so I guess the correct answer would be
that the standard doesn't define warnings.  In fact, I think that a
warning here would be nice; as you say, the compiler knows that the
function is pure virtual, and that any attempt to call it will result
in undefined behavior.

> Interestingly enough, gcc/g++ 2.8.0 came up with a compilation error.
> VC++5.0 came up with a link error.
> Both CC4.1, and Borland C++5.02 compiled and linked fine, but came up
> with a runtime error.
>
> So who is correct?  (or more correct?)

For what definition of "correct"?  According to the standard, CC 4.1 and
Borland are correct -- they'd also be correct if instead of a runtime
diagnostic, they'd reformatted your hard disk.  On the other hand,
although I'm not sure, I think that the standard requires a conforming
compiler to translate the program (with or without a warning), since
the undefined behavior only occurs if the constructor is actually
executed.  In this context, "translate" includes linking, so both g++
and VC++ would be wrong.

IMHO, this is one of the rare cases where the "wrong" behavior is
more useful.  (The "most" correct solution, IMHO, would be to translate
it with a warning that cannot be turned off.)

--
James Kanze    +33 (0)1 39 23 84 71    mailto: kanze@gabi-soft.fr
        +49 (0)69 66 45 33 10    mailto: jkanze@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient=E9e objet --
              -- Beratung in objektorientierter Datenverarbeitung

-----=3D=3D Posted via Deja News, The Leader in Internet Discussion =3D=3D=
-----
http://www.dejanews.com/   Now offering spam-free web-based newsreading
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: loewis@informatik.hu-berlin.de (Martin v. Loewis)
Date: 1998/05/28
Raw View
"Thomas R. Schar" <thomas.schar@dsto.defence.gov.au> writes:

> Well, I guess my first question is,
>     (a) are virtual methods within a constructor statically resolved, or
>          are they still accessed via the vtableptr?
>     (b) if via the vtableptr, then it's understandable.
>     (c) if it is statically resolved, then why doesn't it warn you??
>          it must know it is pure virtual?

This is explained in 10.4, [class.abstract]/6 says

>> Member functions can be called from a constructor (or destructor)
>> of an abstract class; the effect of making a virtual call (10.3) to
>> a pure virtual function directly or indirectly for the object being
>> created (or destroyed) from such a constructor (or destructor) is
>> undefined.

So the program is well-formed, and a compiler should not produce
diagnostics. However, the behaviour of the program is undefined. So
all compilers you've tested are right to give the message they give.

Regards,
Martin
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]