We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

OOP in C

riddhi_barman
on
Medium Priority
302 Views
Last Modified: 2010-05-18
I read somewhere that although it is tough to do OOP in C
(compared to C++) it is not impossible and can be done.
How?
Comment
Watch Question

Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview

Commented:
Encapsulation is easy in C: You simply use a struct.

typedef struct s_GraphicObject{
    int x, y; /* Location of object */
} GraphicObject;

Now you need to encapsulate a few functions for the object:

void GraphicObject_Initialize( GraphicObject *obj)
{
    obj->x = obj-> y = 0;
}

void GraphicObject_Print( FILE *f, GraphicObject *obj)
{
    fprintf( f, "GraphicObject( %d, %d)", obj->x, obj->y);
}

These functions would be prototyped in the header file, along with the typedef.  Then when people want to create an object, they would
    GraphicObject point;
    GraphicObject_Initialize( &point);
    GraphicObject_Print( stdout, &point);

It's a little clunky at points, but it works....

Commented:
Inheritance can be done using containment.  For example, if we extend the GraphicObject given above to be a circle (which adds a radius) you could do:

typedef struct sCircle{
    GraphicObject parent;
    int radius;
} Circle;

and then define:

void Circle_Initialize( Circle *obj)
{
    GraphicObject_Initialize( &obj->parent);
    obj->radius = 1;
}

void Circle_Print( FILE *f, GraphicObject *obj)
{
    fprintf( f, "Circle( ");
    GraphicObject_Print( f, &obj->parent);
    fprintf( f, " raduis= %d)", obj->radius);
}

Commented:
If you want some polymorphism, you'll need to use function pointers:

typedef void (*memberFunction)( void *);
typedef struct s_GraphicObject{
    int x, y; /* Location of object */
    memberFunction Print;
} GraphicObject;

void GraphicObject_Initialize( GraphicObject *obj)
{
    obj->x = obj-> y = 0;
    obj->Print = (memberFunction) GraphicObject_Print;
}

void Circle_Initialize( Circle *obj)
{
    GraphicObject_Initialize( &obj->parent);
    obj->radius = 1;
    obj->parent.Print = (memberFunction) Circle_Print;
}

[Note that I assume that Print only takes a pointer to the object, and not a pointer to the FILE like it did in the previous comments. ]

And then you can print an arbitrary object, like so:
    GraphicObject point;
    GraphicObject_Initialize( &point);
    point.Print( &point);
    Circle myCircle;
    Circle_Initialize( &myCircle);
    myCircle.Print( &myCircle);
Likewise, if you define:
    void foo( GraphicObject *obj)
    {
        obj->Print( obj);
    }
and then call foo( &myCircle), (with a few extra casts) all will work as you would hope it to.

Neat, non?

[We won't talk about multiple inheritance.  I don't think anyone really needs to use it, and if you find an example where it's needed, then you can probably figure out a way to do it yourself...]

Hope all this helps...
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.