Last Updated: February 25, 2016
·
5.726K
· ulrikdamm

Object-like C structs

While the language isn't object oriented, you can still add some object-like features to your C structs, such as subclassing, methods and overloading.

If you want to "subclass" the following struct:

typedef struct {
    int value;
} base_struct;

You just make a new struct, and add the old one at the top:

typedef struct {
    base_struct super;
    int value2;
} sub_struct;

You can then cast the new struct to the old to access its members:

sub_struct s;
s.value2 = 13;
((base_struct)s).value = 37;

Adding "methods" is just a function pointer in a struct:

typedef struct _some_struct {
    int value;
    void (*set_value)(_some_struct *self, int new_value);
} some_struct;

And calling it:

some_struct *s = {};
s->set_value(s, 42);

This method can always be "overloaded" by just changing the function pointer.

5 Responses
Add your response

Nice article!
I have also found this http://www.cs.rit.edu/~ats/books/ooc.pdf interesting.

Best Regards

over 1 year ago ·

Dandy, but _some_struct *self in that definition should be a struct _some_struct *self.

over 1 year ago ·

@SaberUK perhaps because you're an embedded designer, and your platform just isn't up to C++. Maybe 20 MHz MCU with 128 k FLASH and 8 k RAM? That's my life. ;-)

over 1 year ago ·

Reminds me of the Go type-system:


type Base struct {}
type Sub struct {  Base  } //type embedding

http://starp-germany.de/blog/go-specials/

over 1 year ago ·

When I try your example I get this error (gcc):
((base_struct)s).value = 37; // "conversion to non-scalar type requested"

This solution works (with same structs):

sub_struct s;
s.value2 = 13;

base_struct *b;
b = ((base_struct*) &s);
b->value = 43;


printf("%d\n",b->value); //print 43
printf("%d\n",s.value2); //print 13

printf("%p\n",&s); //Points to super base_struct
printf("%p\n",&s.super); //Points to super base_struct
printf("%p\n",&b);
printf("%d",s.super.value); // 43
over 1 year ago ·