UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

  • Index
  • » C++
  • » g++ bug: wrong polymorphism?

#1 2006-08-24 02:28 PM

thinking
Member
Registered: 2005-09-15
Posts: 103

Re: g++ bug: wrong polymorphism?

// this is c++ code

class uber{
   public:
       uber(){ printf("a"); test(); }
       void test(){ printf("1"); }
};

class x: public uber{
   public:
//       x(){ printf("b"); uber(); };  // THIS LINE IS COMMENTED OUT
       void test(){ printf("2"); }

};

int main(int argc,char **argv){
    x *test = new x;
    printf("\n");
    return 0;
}

Offline

#2 2006-08-24 03:24 PM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,239

Re: g++ bug: wrong polymorphism?

A1: OOP is a hyped term which should for all practical purposes be totally ignored. If your code is object oriented or not depends on how you designed it, not what language you used to write it in.

A2: The one that accidentally does what you want is right, all others are wrong.

If the above answers aren't to your satisfaction, here some alternative answers:

IMHO the more logical behaviour is the one of C++. The parent class doesn't know anything about its derived child classes, so whatever function it calls should be the one defined in the class itself, and not some random function with unknown behaviour somewhere else.

Things behind the scene that might cause different behaviour are runtime versus compile time typechecking and early verus late binding, among others. But in the end it's a choice made by the programming language authors.

Offline

#3 2006-08-24 11:21 PM

mlampkin
Administrator
From: Sol 3
Registered: 2002-06-12
Posts: 911
Website

Re: g++ bug: wrong polymorphism?

In line with what i3839 stated... and extending it a bit further...

When dealing with C++, you should be reading the inheritance list from right to left... since that is the order of construction...  e.g. if you had a class heirarchy of A->B->C and were creating some object foo of type A in your code the sequence would be:

1) A foo is undefined
2) constructing foo
3) in constructor A
4) in constructor B
5) in constructor C
6) foo is now type C and construction completes
7) returns to constructor B
8) foo is now type B and construction completes
9) returns to constructor A and foo is ( finally ) a true A type

Now... there IS a reason for this ordering...

Consider if you had A->B ... now if both of them had some function test( )... where the B::test( ) method does nothing... and the A class has some variable of class C declared and the A::test( ) manipulates it...  and in the B constructor you make a call this->test( )...

Ok... soooo...  the sequence when you create a variable of type A... it chains thru its parent class(es) calling their constructor(s)...  in this case B( )... now if your variable considered itself of type A at that point, it would try to call the A::test( )... which would try to manipulate the A object's held C variable... which hasn't been initialized yet... and um...

>>boom<<

Very sad... seriously though... the behavior you are seeing is done to protect you against just such situations...

Btw... I'm not certain about PHP but... Java should be exhibiting the same type of behavior as C++... and in fact that behavior is actually 'enforced' partially thru the requirement that any calls to super( ) be the first statement in a constructor... so I'm curious what distribution / version did you use for your testing... was it one of the Sun JDKs or ?

<additional>
Keep reading...

I actually tested Java and it turns out it does follow the same basic initialization order as C++ construction... BUT with the difference that in a parent class constructor the object is already fully resolved to the upper most child type... so you CAN easily make things go >>BOOM<< in Java... my bad...
</additional>

Michael


"The only difference between me and a madman is that I'm not mad."

Salvador Dali (1904-1989)

Offline

#4 2006-08-31 01:29 PM

thinking
Member
Registered: 2005-09-15
Posts: 103

Re: g++ bug: wrong polymorphism?

hiho
excuse for my late answer
first i did something wrong in my post
the java code shouldn't be "private void test()" but "public void test()"
if it's private it prints the same as c++
if it's public it prints "a2" like php

i tested with
java version "1.4.2_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_03-b02)
on a suse box
and
java version "1.5.0_08"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_08-b03)
on windows

both print "a2" (like php)
if i have time i try the example you gave
thx mlampkin

Offline

#5 2006-09-01 02:10 AM

mlampkin
Administrator
From: Sol 3
Registered: 2002-06-12
Posts: 911
Website

Re: g++ bug: wrong polymorphism?

I honestly didn't think that Java would let a programmer 'shoot themselves in the foot' like that but...

It appears in Java that even when in the parent class constructor - the 'this' object is already resolving to the class type of the child... as opposed to C++ where it follows the resolution steps I outlined previously... I have to dig thru the lang spec and vm docs to see if I can track down the exact ordering / rationale for this...

Anyway - that means ( correcting myself ) you can validly have things like:

class C
{
    public C( )
    {
        System.out.println("C constructor-start");
        System.out.println("C constructor-end" );	
    }
}

class B
{
    public B( )
    {
        System.out.println("B constructor-start");
        System.out.println("B considers itself: " + this );
        test( );
        System.out.println("B constructor-end" );
    }

    protected void test( )
    {
         System.out.println("B test( )");
    }
}

public class A extends B
{
    public static void main( String args[ ] )
    {
        A a = new A();
    }

    private C c = new C();

    public A( )
    {
        super( );
        System.out.println("A constructor-start - after super( )");
        System.out.println("A considers itself: " + this );
        System.out.println("A constructor-end" );
    }

    protected void test()
    {
        System.out.println("A test( ) - start");
        System.out.println("Value of held C object: " + c );
        System.out.println("A test( ) - end");
    }
}

And have it yield the following output:

B constructor-start
B considers itself: [email protected]
A test( ) - start
Value of held C object: null
A test( ) - end
B constructor-end
C constructor-start
C constructor-end
A constructor-start - after super( )
A considers itself: [email protected]
A constructor-end

The point is... that traveling from a parent class back up to the child by calling a method from the parent constructor... where the method is overridden in the child... it can be done... but it additionally means it can / will do things such as accessing instance variable(s) in the child prior to their full initialization... in this case the C type object held by A...

Btw -

Consider that if you do something like this... you are ( imho ) breaking a very important rule for ( OO ) programming... i.e. by attempting to traverse the inheritance tree ( during construction ) in the reverse order of construction, you are putting an unenforcable 'contract' in place for those inheriting from your base class(es)...

And trust me... you really really really don't want to do that... ;-)


Michael


"The only difference between me and a madman is that I'm not mad."

Salvador Dali (1904-1989)

Offline

  • Index
  • » C++
  • » g++ bug: wrong polymorphism?

Board footer

Powered by FluxBB