Re: [dev] Object-Oriented C for interface safety?

From: koneu <koneu93_AT_googlemail.com>
Date: Thu, 27 Nov 2014 13:27:30 +0100

Greetings.

The two things that really make OO languages worthwhile in my opinion
are polymorphism and inheritance. Doing polymorphism and data/code
hiding in C is easy enough with const function pointers. You can just
define public interfaces in their own header like

struct interface {
        void * const this;
        int (* const get_foo)(void *this);
        void (* const set_foo)(void *this, int foo);
        char * (* const get_bar)(void *this);
        void (* const set_bar)(void *this, char *bar);
};

and implement them in "classes" like

struct class {
        int foo;
        char *bar;
};

static int
class_get_foo(void *this) {
        return ((struct class *)this)->foo;
}

static void
class_set_foo(void *this, int foo) {
        ((struct class *)this)->foo = foo;
}

static char*
class_get_bar(void *this) {
        return ((struct class *)this)->bar;
}

static void
class_set_bar(void *this, char *bar) {
        ((struct class *)this)->bar = bar;
}

struct interface
new_class(int foo, char *bar) {
        struct class *this = malloc(sizeof(struct class));
        
        this->foo = foo;
        this->bar = bar;
        return (struct interface){
                this,
                class_get_foo,
                class_set_foo,
                class_get_bar,
                class_set_bar
        };
}

For proper data & code hiding you will want all the code for the
"class" implementing your interface in its own source file and only the
prototype of new_class in a header.
You can then treat all instances of your interface the same, no matter
what "class" implemented them. For example

void
foo(void) {
        struct interface bar = new_class(42, "so far");
        
        printf("%d\n", bar.get_foo(bar.this));
        free(bar.this);
        bar = new_class2();
        /* who knows... ? */
        bar.set_bar(bar.this, "and thanks for all the fish");
        printf("%s\n", bar.get_foo(bar.this));
}

Of course each "class" can only implement one interface.

Inheritance is harder to do, it usually involves nested structs and
doesn't play well with the above implementation of interfaces.
Have fun experiencing C and its beautiful simplicity. And try googling
"c programming" instead of "c". ;)

Sincerely,
Received on Thu Nov 27 2014 - 13:27:30 CET

This archive was generated by hypermail 2.3.0 : Thu Nov 27 2014 - 13:36:09 CET