Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Experiment: Object Oriented C? [duplicate]

Tags:

c

object

macros

Possible Duplicate:
Can you write object oriented code in C?

Hi!

Just for the fun of it, I've been experimenting these last two days with creating a very simple, very straightforward object environment in pure C. I've been toying around with macros, dynamic linking, type-description structures and the like, and I've arrived at the following:

string_o str = new(String, "hello world");
list_o list = new(List);

List.pushf(list, str);

printf("In the list: \"%s\"\n",
       String.text(List.popf(list)));

delete(list);
delete(str);

Looks and works kinda nice, but I can't figure a way to fake instance methods. I can't get past Class.function(instance), not without global macro replacements for function names, which defeats the purpose of encapsulation.

Again, this is an experiment, just for the challenge and the fun =). Can you guys help me figure out a way to do this? I don't want to use additional preprocessing, only plain C and GCC macros.

edit> forgot to say -- I don't want each instance to contain the function pointers in its structure. That would give me method syntax alright, but it would mean that a 4-byte data object would have a dozen function pointers copied over to each instance. That's kinda like cheating =P haha

Thanks in advance!

like image 548
slezica Avatar asked Nov 05 '10 05:11

slezica


1 Answers

Object orientation in C is normally done with function pointers. That means a structure which contains not only the data for an instance but the functions to call as well.

It's the easiest way to do inheritance and polymorphism in C. By way of example, here's an object-orientd communications example.

It only has one method open but you can see how that differs for the TCP and HTML sub-classes. By having an initialisation routine which sets the a class-specific function, you get polymorphism.

#include <stdio.h>

// The top-level class.

typedef struct _tCommClass {
    int (*open)(struct _tCommClass *self, char *fspec);
} tCommClass;

// Function for the TCP class.

static int tcpOpen (tCommClass *tcp, char *fspec) {
    printf ("Opening TCP: %s\n", fspec);
    return 0;
}
static int tcpInit (tCommClass *tcp) {
    tcp->open = &tcpOpen;
    return 0;
}

// Function for the HTML class.

static int htmlOpen (tCommClass *html, char *fspec) {
    printf ("Opening HTML: %s\n", fspec);
    return 0;
}
static int htmlInit (tCommClass *html) {
    html->open = &htmlOpen;
    return 0;
}

// Test program.

int main (void) {
    int status;
    tCommClass commTcp, commHtml;

    // Same base class but initialized to different sub-classes.
    tcpInit (&commTcp);
    htmlInit (&commHtml);

    // Called in exactly the same manner.

    status = (commTcp.open)(&commTcp, "bigiron.box.com:5000");
    status = (commHtml.open)(&commHtml, "http://www.microsoft.com");

    return 0;
}

A more complete answer can be found here.

In response to your comment:

I don't want the functions contained in every single instance.

You're probably right. It's unnecessary to duplicate that information when it will be the same for every instance of a single class.

There's a simple way around that. Rather than having every instance carry its own set of function pointers, you create one structure holding them for the class, then each instance gets a pointer to that structure.

That will save quite a bit of space at the (minimal) cost of having to do two levels of indirection to call a function.

like image 184
paxdiablo Avatar answered Nov 15 '22 21:11

paxdiablo