[comp.lang.c++] polymorphism on base objects?

dpg@extro.ucc.su.OZ.AU (D P Gilbert) (05/14/91)

I was experimenting with polymorphism to see if it works through a
function that takes a reference to a base class and got the following
surprises. 2 compilers (SUN C++ and Comeau on ix/386) based on cfront
2.0 gave the same results. The following sections in the ARM throw
some light on this (but I'm still confused): 4.7 (reference conversion),
5.17 (assignment operator), and 10.2 (Virtual functions).


#include <iostream.h>

class Base {
public:
    virtual void className() const { cout << "Class name: Base\n"; }
};
class D1 : public Base {
public:
    void className() const { cout << "Class name: D1\n"; }
};
class D2 : public Base {
public:
    void className() const { cout << "Class name: D2\n"; }
};

void test_a(const Base &bas) { bas.className(); }   // expect polymorphism
void test_b(const Base bas) { bas.className(); }    // don't expect ...

main()
{
    Base    b;
    D1      d1;
    D2      d2;
    Base    bb(d2);
                                        // Hoped for:
    cout << "test_a(b) : "; test_a(b);      //  Class name: Base
    cout << "test_a(d1) : "; test_a(d1);    //  Class name: D1
    cout << "test_a(bb) : "; test_a(bb);    //  Class name: Base
    cout << "test_b(b) : "; test_b(b);      //  Class name: Base
    cout << "test_b(d1) : "; test_b(d1);    //  Class name: Base
    cout << "test_b(bb) : "; test_b(bb);    //  Class name: Base
}

Got the following output:

test_a(b) : Class name: Base
test_a(d1) : Class name: D1
test_a(bb) : Class name: D2         ???
test_b(b) : Class name: Base
test_b(d1) : Class name: D1         ???
test_b(bb) : Class name: D2         ???

These last 2 results seem to indicate I can get polymorphism via
base objects? Apologies is this is a stupid question.

Thanks   Doug Gilbert

jgro@lia (Jeremy Grodberg) (05/15/91)

In article <dpg.674226630@extro> dpg@extro.ucc.su.OZ.AU (D P Gilbert) writes:
>I was experimenting with polymorphism to see if it works through a
>function that takes a reference to a base class and got the following
>surprises. 2 compilers (SUN C++ and Comeau on ix/386) based on cfront
>[2.0 gave the same results.]
> [ example omitted ]
>These last 2 results seem to indicate I can get polymorphism via
>base objects? Apologies if this is a stupid question.

This is not a stupid question, it is a bug in cfront 2.0.  
Under certain circumstances (the details of which I do not know), the
default copy constructor incorrectly copies over the vtable pointer,
giving the new object the wrong virtual functions.  I belive this bug does
not show up if the object being copied is a different size from the
object being copied to, which is why it does not cause a lot of problems
in real code (since derived classes almost always add at least one
member).

The results you expected were in fact the correct results, and the compiler 
was wrong.
-- 
Jeremy Grodberg      "Show me a new widget that's bug-free, and I'll show
jgro@lia.com         you something that's been through several releases."

mittle@blinn.watson.ibm.com (Josh Mittleman) (05/16/91)

I agree that your results are confusing, and I think that they are simply
wrong.  I compiled your code with the ATT v2.1 compiler, and I did not
reproduce your results.  My output was what you expected in the first
place: 

test_a(b) : Class name: Base
test_a(d1) : Class name: D1
test_a(bb) : Class name: Base
test_b(b) : Class name: Base
test_b(d1) : Class name: Base
test_b(bb) : Class name: Base

It is certainly incorrect to get polymorphism through a base class object,
as opposed to through a base class pointer or reference.  A Base is a Base,
and cannot be anything but a Base.

===========================================================================
Josh Mittleman (mittle@watson.ibm.com or joshua@paul.rutgers.edu)
J2-C28 T.J. Watson Research Center, PO Box 704, Yorktown Heights, NY  10598

comeau@ditka.Chicago.COM (Greg Comeau) (05/17/91)

In article <dpg.674226630@extro> dpg@extro.ucc.su.OZ.AU (D P Gilbert) writes:
>I was experimenting with polymorphism to see if it works through a
>function that takes a reference to a base class and got the following
>surprises. 2 compilers (SUN C++ and Comeau on ix/386) based on cfront
>2.0 gave the same results.

Don't be confused.  As best I can see that was a bug in cfront 2.0.  As 2.1,
amongst other things, was a maintenance release, the output you hoped
to see is the one properly ported 2.1 cfronts give.

- Greg
-- 
	 Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418
                          Producers of Comeau C++ 2.1
          Here:attmail.com!csanta!comeau / BIX:comeau / CIS:72331,3421
                     Voice:718-945-0009 / Fax:718-441-2310