11

Could you suggest a syntax for the C language to use it in a similar way than an object-oriented language? I know that they cannot be the same and that some keywords aren't present in C, but I'm wondering if there is a way to take advantage of certain aspects (like inheritance) even in a C program.

zoul
  • 102,279
  • 44
  • 260
  • 354
Maurizio Reginelli
  • 3,152
  • 2
  • 27
  • 41
  • 1
    exact duplicates http://stackoverflow.com/questions/2181079/object-oriented-programming-in-c/2181142#2181142 http://stackoverflow.com/questions/351733/can-you-write-object-oriented-code-in-c – N 1.1 Feb 28 '10 at 20:55
  • Sorry I didn't see those questions. If you want, you can close this post. – Maurizio Reginelli Feb 28 '10 at 21:04
  • i can't close it, but i would suggest you to google 'site:stackoverflow.com question-keywords' before asking a question :) – N 1.1 Feb 28 '10 at 21:07
  • I accept your advice, but I see that you have to do the same thing... http://stackoverflow.com/questions/2345951/c-blogs-that-you-follow-regularly-closed :-) – Maurizio Reginelli Feb 28 '10 at 21:10
  • Well, if you read it closely, its not a duplicate, I have even stated it there. I wanted some resources for a programmer who already knows the basics whereas the duplicate (supposedly) is about a programmer who is starting to learn C. You see, a lot of difference. But, democracy ruled there! :P – N 1.1 Feb 28 '10 at 21:30
  • I once took the c++ virtual functions example from wikipedia entry and implemented it with a virtual table in C. I timed the execution of the two and they were exactly the same in terms of speed give or take a little error for other running processes. At a basic level c and c++ are identical. Even class construction is identical as they both dynamically allocate and assign function pointers. Doing OOP in C might be preferable if you have time and want to guarantee upmost portability. Otherwise just use c++ for the oop part and use the C standard library b/c performance will be the same. –  Nov 05 '12 at 17:45

5 Answers5

10

You can implement polymorphism with regular functions and virtual tables (vtables). Here's a pretty neat system that I invented (based on C++) for a programming exercise: alt text
(source: goblin.tkk.fi)

The constructors allocate memory and then call the class' init function where the memory is initialized. Each init function should also contain a static vtable struct that contains the virtual function pointers (NULL for pure virtual). Derived class init functions call the superclass init function before doing anything else.

A very nice API can be created by implementing the virtual function wrappers (not to be confused with the functions pointed to by the vtables) as follows (add static inline in front of it, if you do this in the header):

int playerGuess(Player* this) { return this->vtable->guess(this); }

Single inheritance can be done by abusing the binary layout of a struct: alt text
(source: goblin.tkk.fi)

Notice that multiple inheritance is messier as then you often need to adjust the pointer value when casting between types of the hierarchy.

Other type-specific data can be added to the virtual tables as well. Examples include runtime type info (e.g. type name as a string), linking to superclass vtable and the destructor chain. You probably want virtual destructors where derived class destructor demotes the object to its super class and then recursively calls the destructor of that and so on, until the base class destructor is reached and that finally frees the struct.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Tronic
  • 10,250
  • 2
  • 41
  • 53
  • 1
    +1 very nice graphics. Now I have to favorite this question. See what you've done? – wheaties Feb 28 '10 at 20:45
  • exact duplicate http://stackoverflow.com/questions/2181079/object-oriented-programming-in-c/2181142#2181142 – N 1.1 Feb 28 '10 at 20:54
  • I did some minor adjustments to better suit this question, but yes - it is a copy&paste :) – Tronic Feb 28 '10 at 21:21
2

There is the GObject library:

The GLib Object System, or GObject, is a free software library (covered by the LGPL) that provides a portable object system and transparent cross-language interoperability. GObject is designed for use both directly in C programs and through bindings to other languages.

Otto Allmendinger
  • 27,448
  • 7
  • 68
  • 79
2

The traditional solution is the function pointer struct. I emphasize traditional. I can tell you what sort of code I wrote in PL/I and C years ago, but I don't claim to speak for the state of the 'art' if you can call this art.

There are many variations on this, and the below is a bit of a compromise.

struct SortOfAnAbstractClass {
   int (*function1)(SortOfAnAbstractClass* this, int arg1, int arg2, char * arg3);
   void (*function2)(SortOfAnAbstractClass* this, char *arg);
};

struct SortOfDerived {
   struct SortOfAnAbstractClass base;
   int instanceVariable1;
};

SortOfAnAbstractClass getMeOne() {
     SortOfDerived *d = malloc(sizeof SortOfDerived);
     memset(d, 0, sizeof SortOfDerived);
     d->function1 = myf1;
     d->function2 = myf2;
     return &d->base;
};

and then 'myf1' and 'myf2' cast their 'this' parameters and go to town. You can extend this to look ever more like a full virtual dispatch.

Another common variation from the mists of time:

struct SortOfAClass {
   void *creatorInfo;
   int (*function1)(SortOfAnAbstractClass* this, int arg1, int arg2, char * arg3);
   void (*function2)(SortOfAnAbstractClass* this, char *arg);
};

In this variation, there's no inheritance by inclusion. The derived classes each put their private state into their own object in creatorInfo.

bmargulies
  • 97,814
  • 39
  • 186
  • 310
  • ... I don't see `struct SortOfAnAbstractBase` defined anywhere. It can't be `struct SortOfAnAbstractClass` since you wouldn't want to put a virtual pointer table in every object instance. – Mike D. Feb 28 '10 at 20:22
1

Take a look at the GObject library: http://library.gnome.org/devel/gobject/2.22/.

Kyle Lutz
  • 7,966
  • 2
  • 20
  • 23
0

There are many variations to doing OO programming in C. The way I prefer to do it is to define one class per a header file. You'll notice a constructor new_testclass() which just initializes your function pointers and returns a pointer to an allocated class/struct. Also any function takes pointer to the class in the first parameter (something c++ does, but conceals).

testclass.h

#ifndef MALLOC_H
    #include<malloc.h>
#endif
struct _testclass 
{
    int a;
    int b;
    int (*sum)(struct _testclass *obj);
};

typedef struct _testclass testclass;

int f_sum (testclass *obj)
{
    return obj->a + obj->b;
}

testclass* new_testclass()
{
    testclass *temp;
    temp = (testclass*)malloc(sizeof(testclass));
    temp->sum = &f_sum;
    return temp;
}

Then you can simply use it.

testclass.c

#include <stdio.h>
#include "testclass.h"
int _tmain(int argc, _TCHAR* argv[])
{
    int result;
    testclass *testclass1;
    testclass1 = new_testclass();
    testclass1->a = 5;
    testclass1->b = 8;
    result = testclass1->sum(testclass1);
    printf("%d\n",result);
    free(testclass1);
    return 0;
}

Of course there are several important aspects of object oriented programming missing here, but this provides a simple method for basic abstraction. I'd imagine inheritance would require some kind of funky preprocessor trick if it could be done at all.