Polymorphism in C

Discussion in 'C Programming' started by Mike, Feb 1, 2004.

  1. Mike

    Mike Guest

    Attached below is a file that implements polymorphism in C. It's
    loosly based on the way Miro Samek describes it
    (http://www.embedded.com/97/fe29712.htm). I found the article a
    little confusing so I made some changes and came up with wat's
    below. It appears to work, but I've written plenty of programs before
    that seemed to work, but didn't. Anyone willing to take a look, and
    check for correcness? I would also love to hear suggestions on how to
    simplify, improve upon, or increase the power of this method.

    -Goal-
    To have an array containing various shapes, and draw (just print
    statement in this app) them, without knowing what they are.

    -Implementation-
    structs are used as classes.
    A base class, shape_t is inherited by child classes, circle_t and
    rectangle_t.
    Inheritance is accomplished by including shape_t as the first member
    in the childs structure (it has to be first).
    A generic class is created, any_shape_t. A pointer of any_shape_t
    type, can point to objects of type circle_t and rectangle_t.
    Objects created must in initialized by a constuctor function.

    This file was tested with GCC (with no warnings) on Linux.
    Dumping what's below into a single file should do the trick.
    This is the output I got:
    Draw a circle of radius 17.
    Draw a rectangle of length 6 and width 5.

    /********************* source *******************/

    #include <stdio.h>

    typedef struct
    {
    void (*Draw)();
    }shape_t, *p_shape_t;

    typedef struct
    {
    shape_t shape;
    }any_shape_t;

    typedef struct
    {
    shape_t shape;
    int radius;
    }circle_t;

    typedef struct
    {
    shape_t shape;
    int length;
    int width;
    }rectangle_t;

    circle_t* Circle_ctor(circle_t* p_c, int radius);
    void Circle_draw(circle_t* p_c);

    rectangle_t* Rectangle_ctor(rectangle_t* p_r, int length, int width);
    void Rectangle_draw(rectangle_t* p_r);


    /********* circle *********/
    circle_t* Circle_ctor(circle_t* p_c, int radius)
    {
    p_c->radius = radius;
    p_c->shape.Draw = Circle_draw;
    return p_c;
    }

    void Circle_draw(circle_t* p_c)
    {
    printf("Draw a circle of radius %d.\n", p_c->radius);
    }


    /********* rectangle *********/
    rectangle_t* Rectangle_ctor(rectangle_t* p_r, int length, int width)
    {
    p_r->length = length;
    p_r->width = width;
    p_r->shape.Draw = Rectangle_draw;
    return p_r;
    }

    void Rectangle_draw(rectangle_t* p_r)
    {
    printf("Draw a rectangle of length %d and width %d.\n", p_r->length, p_r->width);
    }


    /********* main *********/
    int main()
    {
    circle_t c1;
    circle_t* p_c1;
    rectangle_t r1;
    rectangle_t* p_r1;
    any_shape_t* p_shapes[] = {0,0,0,0,0,0};
    int i;


    p_c1 = Circle_ctor(&c1, 17);
    p_r1 = Rectangle_ctor(&r1, 6, 5);

    p_shapes[0] = (any_shape_t*)p_c1;
    p_shapes[1] = (any_shape_t*)p_r1;

    for(i=0; p_shapes != 0; i++)
    p_shapes->shape.Draw(p_shapes);

    return 0;
    }
     
    Mike, Feb 1, 2004
    #1
    1. Advertising

  2. Mike

    Jack Klein Guest

    On 31 Jan 2004 18:16:31 -0800, (Mike) wrote in
    comp.lang.c:

    > Attached below is a file that implements polymorphism in C. It's
    > loosly based on the way Miro Samek describes it
    > (http://www.embedded.com/97/fe29712.htm). I found the article a
    > little confusing so I made some changes and came up with wat's
    > below. It appears to work, but I've written plenty of programs before
    > that seemed to work, but didn't. Anyone willing to take a look, and
    > check for correcness? I would also love to hear suggestions on how to
    > simplify, improve upon, or increase the power of this method.


    If you want to simplify this method, use C++. Really. That's what it
    is for. If you wanted to expand your example by having more than one
    "member" function, you would need to either increase the size of each
    structure for more function pointers, or invent your own "vtable".
    Why do all the work when any C++ compiler, even a 10 year old one,
    will do it for you for free?

    Attempting to write C++ in C generally leads to results that are
    neither good C nor good C++. At least I haven't seen such an effort
    yet that was.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Feb 1, 2004
    #2
    1. Advertising

  3. Mike

    Malcolm Guest

    "Jack Klein" <> wrote in message
    >
    > Attempting to write C++ in C generally leads to results that are
    > neither good C nor good C++. At least I haven't seen such an effort
    > yet that was.
    >

    Direct X (the Microsoft Windows game library) uses a component technology
    called com, which is basically a C++ class. However there is also a C
    interface, which is usable, if a little clunky.
     
    Malcolm, Feb 1, 2004
    #3
  4. On Sun, 1 Feb 2004, Jack Klein wrote:

    > > Attached below is a file that implements polymorphism in C. It's
    > > loosly based on the way Miro Samek describes it
    > > (http://www.embedded.com/97/fe29712.htm). I found the article a
    > > little confusing so I made some changes and came up with wat's
    > > below. It appears to work, but I've written plenty of programs before
    > > that seemed to work, but didn't. Anyone willing to take a look, and
    > > check for correcness? I would also love to hear suggestions on how to
    > > simplify, improve upon, or increase the power of this method.

    >
    > If you want to simplify this method, use C++. Really. That's what it
    > is for. If you wanted to expand your example by having more than one
    > "member" function, you would need to either increase the size of each
    > structure for more function pointers, or invent your own "vtable".
    > Why do all the work when any C++ compiler, even a 10 year old one,
    > will do it for you for free?
    >
    > Attempting to write C++ in C generally leads to results that are
    > neither good C nor good C++. At least I haven't seen such an effort
    > yet that was.


    Funny, I used to think that e.g. encapsulating file I/O that way was
    a clever method of making the interface more powerful and portable in
    various libraries I've seen..
     
    Jarno A Wuolijoki, Feb 1, 2004
    #4
  5. Mike

    xarax Guest

    "Jack Klein" <> wrote in message
    news:...
    > On 31 Jan 2004 18:16:31 -0800, (Mike) wrote in
    > comp.lang.c:
    >
    > > Attached below is a file that implements polymorphism in C. It's
    > > loosly based on the way Miro Samek describes it
    > > (http://www.embedded.com/97/fe29712.htm). I found the article a
    > > little confusing so I made some changes and came up with wat's
    > > below. It appears to work, but I've written plenty of programs before
    > > that seemed to work, but didn't. Anyone willing to take a look, and
    > > check for correcness? I would also love to hear suggestions on how to
    > > simplify, improve upon, or increase the power of this method.

    >
    > If you want to simplify this method, use C++. Really. That's what it
    > is for. If you wanted to expand your example by having more than one
    > "member" function, you would need to either increase the size of each
    > structure for more function pointers, or invent your own "vtable".
    > Why do all the work when any C++ compiler, even a 10 year old one,
    > will do it for you for free?
    >
    > Attempting to write C++ in C generally leads to results that are
    > neither good C nor good C++. At least I haven't seen such an effort
    > yet that was.


    There are times when C++ is just not a good choice
    compared with C. The polymorphic technique presented
    is extremely old and it only supports single-inheritance.
    However, it is quite viable if there is an automated way
    of generating the rather complex supporting C code for
    instance construction and destruction.

    I use a very similar technique in a TCP/IP component
    that defines each message packet as a "class". The complexity
    of keeping everything in synch (which a C++ compiler would
    do automatically) is handled by a program generator that
    accepts XML input that specifies the message packet fields
    and types, then spits out the appropriate supporting C
    code (and Java) that implements the polymorphic code. Functions
    are represented in their own namespace by using function pointer
    fields within a struct. A supporting constructor function
    is generated that allocates the memory for the instance
    data and assigns the function pointers to the class struct.
    Parent constructors/destructors are automatically called as
    needed when an instance is created or destroyed. Similar
    Java classes are also generated so that my application can
    send the message packets between Java and C.

    There is no way that I could possibly keep everything
    organized in C (and Java) without automation. At the
    "client level" where I invoke the polymorphic methods,
    it is simply a matter of double indirection (i.e., two
    dereferences via ->) to get the function pointer and
    pass the parameters, including the required first parameter
    that points to the object instance. The "client level"
    usage is very simple and easy to use, so it pays off
    with higher productivity.

    I have a GUI front-end for the program generator. Adding
    a new field to message packet, or creating new message
    packets is just a point-and-click. All of the Java and
    C code is regenerated (thousands of lines of code). I
    recompile the application and it's ready to go.

    I suggest reading "Object Oriented Software Construction"
    (2nd Edition) by Bertrand Meyer, before getting too deep
    into this polymorphic C thing. Thinking in object oriented
    terms and understanding how object oriented semantics are
    expressed and represented is vital before you get too
    deep into the C implementation details.

    2 cents worth. Your mileage may vary.


    --
    ----------------------------
    Jeffrey D. Smith
    Farsight Systems Corporation
    24 BURLINGTON DRIVE
    LONGMONT, CO 80501-6906
    http://www.farsight-systems.com
    z/Debug debugs your Systems/C programs running on IBM z/OS!
    Are ISV upgrade fees too high? Check our custom product development!
     
    xarax, Feb 1, 2004
    #5
  6. (Mike) wrote in message news:<>...
    > Attached below is a file that implements polymorphism in C. It's
    > loosly based on the way Miro Samek describes it
    > (http://www.embedded.com/97/fe29712.htm). I found the article a
    > little confusing so I made some changes and came up with wat's
    > below. It appears to work, but I've written plenty of programs before
    > that seemed to work, but didn't. Anyone willing to take a look, and
    > check for correcness? I would also love to hear suggestions on how to
    > simplify, improve upon, or increase the power of this method.
    >


    For more info you can see the lwc preprocessor which is
    something like a C++ to C converter.

    http://students.ceid.upatras.gr/~sxanth/lwc/

    And an example for polymorphism:

    http://students.ceid.upatras.gr/~sxanth/lwc/ex4.html

    > /********************* source *******************/
    >
    > #include <stdio.h>
    >
    > typedef struct
    > {
    > void (*Draw)();
    > }shape_t, *p_shape_t;


    Here, shouldn't the prototype of Draw() have an argument??

    It should be more like:

    void (*Draw) (p_shape_t *this);

    And the Draw() function should dispatch the 'this' argument by
    the offset (zero indeed in this example) that points to a circle or rectanle....

    Generally, the concept of callbacks is used very frequently (operating
    systems:device drivers, for example).


    stelios
     
    stelios xanthakis, Feb 1, 2004
    #6
  7. Mike

    SenderX Guest

    > -Goal-
    > To have an array containing various shapes, and draw (just print
    > statement in this app) them, without knowing what they are.


    That is VERY easy in C, believe it or not.


    ( pseudo code! )



    /* SHAPE INTERFACE */


    IShape.h
    -------------------

    /* Shape interface */
    typedef struct IShape_
    {
    void *pImpl;
    void ( *fpDraw ) ( void *pThis );
    void ( *fpFree ) ( void *pThis );

    } IShape;


    /* Shape C API */

    #define ShapeDraw( i ) ( (i)->fpDraw( (i)->pImpl ) )
    #define ShapeFree( i ) ( (i)->fpFree( (i)->pImpl ) )




    /* CIRCLE OBJECT */


    Cricle.h
    -------------------

    #include "IShape.h"


    /* Allocs a circle */
    extern int CircleAlloc( IShape *pIFace, /* circle stuff */ );



    Circle.c
    -------------------

    /* Circle object */
    typedef struct Circle_
    {
    int iVal1;
    /* ... */

    } Circle;


    /* Draws a circle */
    static void CircleDraw( Circle *pThis )
    {
    /* ... */
    }


    /* Frees a circle */
    static void CircleFree( Circle *pThis )
    {
    /* ... */

    free( pThis );
    }


    /* Allocs a circle */
    int CircleAlloc( IShape *pIFace, /* circle stuff */ )
    {
    Circle *pThis = malloc( sizeof( *pThis ) );

    /* Init circle */

    /* Init shape interface */
    pIFace->pImpl = pThis;
    pIFace->fpFree = CircleFree;
    pIFace->fpDraw = CircleDraw;

    return 0;
    }





    /* APPLICATION */


    DrawShapes.c
    -------------------

    #include "Circle.h"

    int main( void )
    {
    int i;

    /* Ten shapes */
    IShape s[10];


    /* Alloc the circles */
    for ( i = 0; i < 10; ++i )
    {
    CircleAlloc( &s, /* whatever */ );
    }


    /* Draw the circles */
    for ( i = 0; i < 10; ++i )
    {
    ShapeDraw( &s );
    }


    /* Free the circles */
    for ( i = 0; i < 10; ++i )
    {
    ShapeFree( &s );
    }


    return 0;
    }


    As you can see, this is fairly clean and will allow for any number of
    different shapes to use the IShape interface.

    OOP in C is very nice, IMHO...

    ;)
     
    SenderX, Feb 1, 2004
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kevin Lawrence

    Polymorphism in GridView (ASP.Net 2.0)

    Kevin Lawrence, Feb 16, 2006, in forum: ASP .Net
    Replies:
    0
    Views:
    875
    Kevin Lawrence
    Feb 16, 2006
  2. Sony Antony

    Polymorphism in xml ??

    Sony Antony, Aug 26, 2003, in forum: Java
    Replies:
    0
    Views:
    577
    Sony Antony
    Aug 26, 2003
  3. Osaman
    Replies:
    2
    Views:
    460
    John C. Bollinger
    Jan 5, 2004
  4. Tony Morris

    polymorphism

    Tony Morris, Mar 7, 2004, in forum: Java
    Replies:
    1
    Views:
    741
    sonali
    Mar 7, 2004
  5. Krivenok Dmitry
    Replies:
    13
    Views:
    1,492
    Axter
    Jun 1, 2006
Loading...

Share This Page