C como lenguaje orientado a objetos

¿Podría sugerir una syntax para que el lenguaje C la use de manera similar a un lenguaje orientado a objetos? Sé que no pueden ser iguales y que algunas palabras clave no están presentes en C, pero me pregunto si hay una manera de aprovechar ciertos aspectos (como la herencia) incluso en un progtwig en C.

Puede implementar polymorphism con funciones regulares y tablas virtuales (vtables). Aquí hay un sistema bastante bueno que inventé (basado en C ++) para un ejercicio de progtwigción: texto alternativo

Los constructores asignan memoria y luego llaman a la función de inicio de la clase donde se inicializa la memoria. Cada función init también debe contener una estructura vtable estática que contenga los punteros de función virtual (NULL para virtual puro). Las funciones de inicio de clase derivadas llaman a la función de inicio de superclase antes de hacer cualquier otra cosa.

Se puede crear una API muy agradable implementando los envoltorios de funciones virtuales (no debe confundirse con las funciones señaladas por vtables) de la siguiente manera (agregue una static inline delante de ella, si lo hace en el encabezado):

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

La herencia única se puede hacer abusando del diseño binario de una estructura: texto alternativo

Tenga en cuenta que la herencia múltiple es más desordenada, ya que a menudo necesita ajustar el valor del puntero al realizar la conversión entre los tipos de jerarquía.

También se pueden agregar otros datos específicos de tipo a las tablas virtuales. Los ejemplos incluyen información de tipo de tiempo de ejecución (por ejemplo, el nombre del tipo como una cadena), que se vincula a superclass vtable y la cadena del destructor. Es probable que desee destructores virtuales, donde el destructor de clase derivada devuelve el objeto a su superclase y luego recursivamente llama al destructor de eso y así sucesivamente, hasta que se alcanza el destructor de clase base y eso finalmente libera la estructura.

Hay la librería GObject :

El sistema de objetos GLib, o GObject, es una biblioteca de software libre (cubierta por la LGPL) que proporciona un sistema de objetos portátil y una interoperabilidad transparente entre idiomas. GObject está diseñado para usarse directamente en progtwigs C y mediante enlaces a otros idiomas.

La solución tradicional es la función puntero de la función. Destaco lo tradicional. Puedo decirle qué tipo de código escribí en PL / I y C hace años, pero no pretendo hablar en nombre del estado del ‘arte’ si puede llamar a este arte.

Hay muchas variaciones en esto, y el siguiente es un poco de compromiso.

 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; }; 

y luego ‘myf1’ y ‘myf2’ emiten sus parámetros ‘este’ y se dirigen a la ciudad. Puede extender esto para que se parezca cada vez más a un despacho virtual completo.

Otra variación común de las nieblas del tiempo:

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

En esta variación, no hay herencia por inclusión. Cada una de las clases derivadas pone su estado privado en su propio objeto en creatorInfo.

Eche un vistazo a la biblioteca de GObject: http://library.gnome.org/devel/gobject/2.22/ .

Hay muchas variaciones para hacer la progtwigción OO en C. La forma en que prefiero hacerlo es definir una clase por archivo de encabezado. Notará un constructor new_testclass() que simplemente inicializa los punteros de sus funciones y devuelve un puntero a una clase / estructura asignada. Además, cualquier función lleva el puntero a la clase en el primer parámetro (algo que c ++ hace, pero oculta).

testclass.h

 #ifndef MALLOC_H #include #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; } 

Entonces simplemente puedes usarlo.

testclass.c

 #include  #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; } 

Por supuesto, aquí faltan varios aspectos importantes de la progtwigción orientada a objetos, pero esto proporciona un método simple para la abstracción básica. Me imagino que la herencia requeriría algún tipo de truco de preprocesador funky si pudiera hacerse.