Topic: ARM ambiguity about member initializers and virtual functions


Author: ellis@parc.xerox.com (John Ellis)
Date: 27 Jan 93 00:45:05 GMT
Raw View
For the purposes of binding virtual functions, is a member initializer
considered part of the constructor in which it appears?  The answer
might seem obviously yes, but the ARM appears contradictory on this point.

Consider this test program:

    #include <iostream.h>

    struct A {
        A() {f();}
        virtual int f() {
            cout << "In A::f.\n";
            return 0;}
        int g() {return f();}};

    struct B: A {
        B(): i( g() ) {g();}
        int i;
        virtual int f() {
            cout << "In B::f.\n";
            return 0;}};

    void main() {B b;}

Three compilers we tested believe that member initializers are part of a
constructor as regards virtual functions.  They produced this output:

    In A::f.
    In B::f.
    In B::f.

whereas a fourth compiler, known for its rigid adherence to the
standard, has a contrary belief:

    In A::f.
    In A::f.
    In B::f.

The natural interpretation, that a member initializer is part of its
constructor, comes from two passages in the ARM:

    Page 294, 12.7: Member functions may be called in constructors and
    destructors.  ... The function called will be the one defined in
    the constructor's (or destructor's) own class or its bases, but
    *not* any function overriding it in a derived class.

    Page 294, 12.6.2: A mem-initializer is evaluated in the scope of
    the constructor in which it appears.

But some earlier commentary clearly contradicts the natural
interpretation:

    Page 233, 10.9c: When B::B() is executing, the C part of the
    object being constructed exists only as raw storage and cannot be
    accessed through a virtual function.  The available f() is A::f().
    The first point at which C::f() can be called as f() is the first
    *statement* in the constructor C::C(). [emphasis added]

This clearly states that a class's virtual functions are not available
before the first statement of a constructor.  Since member
initializers are executed before the statements of the constructor:

    Page 292, 12.6.2: ...then the members are initialized...then the
    body of D::D() is executed (12.1).

this implies that a class's virtual functions are not available to a
member initializer.

Is section 10.9c wrong?