2010-02-28 23 views
11

¿Podría sugerir una sintaxis para que el lenguaje C lo use de forma 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 forma de aprovechar ciertos aspectos (como la herencia) incluso en un programa C.C como un lenguaje orientado a objetos

+1

duplicados exactos http://stackoverflow.com/questions/2181079/object-oriented-programming-in-c/2181142#2181142 http://stackoverflow.com/questions/351733/can-you-write-object- código-orientado-en-c –

+0

Lamento no haber visto esas preguntas. Si lo desea, puede cerrar esta publicación. –

+0

no puedo cerrarlo, pero te sugiero que consultes google 'site: stackoverflow.com question-keywords' antes de hacer una pregunta :) –

Respuesta

10

Puede implementar polimorfismo con funciones regulares y tablas virtuales (vtables). Este es un sistema bastante ingenioso que inventé (basado en C++) para un ejercicio de programación: alt text

Los constructores asignan memoria y luego llaman a la función init 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 pura virtual). Las funciones de inicio de clase derivadas llaman a la función init de la superclase antes de hacer cualquier otra cosa.

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

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

herencia simple se puede efectuar mediante el abuso de la distribución binaria de una estructura: alt text

en cuenta que la herencia múltiple es más desordenado como entonces a menudo es necesario ajustar el valor del puntero cuando se cuelan entre los tipos de la jerarquía.

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

+1

+1 gráficos muy agradables. Ahora tengo que preferir esta pregunta. Mira lo que has hecho? – wheaties

+0

duplicado exacto http://stackoverflow.com/questions/2181079/object-oriented-programming-in-c/2181142#2181142 –

+0

Hice algunos ajustes menores para adaptarse mejor a esta pregunta, pero sí, es una copia y pega :) – Tronic

2

Existe la GObject library:

el sistema de objetos GLib, o GObject, es una biblioteca de software libre (cubierto por la LGPL) que proporciona un sistema de objeto portátil y transparente interoperabilidad entre lenguajes. GObject está diseñado para usarse tanto en programas C como a través de enlaces a otros lenguajes.

+1

+1 por no reinventar la rueda –

+1

-1 por no dejar que alguien aprenda haciendo cosas – Nisanio

2

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

Existen muchas variaciones en esto, y el siguiente es un poco comprometedor.

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 'this' y van a la ciudad. Puede ampliar esto para que se parezca cada vez más a un despacho virtual completo.

Otra variación común de la bruma 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 la inclusión. Las clases derivadas cada una pone su estado privado en su propio objeto en creatorInfo.

+0

... No veo 'struct SortOfAnAbstractBase' definido en ninguna parte. No puede ser 'struct SortOfAnAbstractClass' ya que no le gustaría poner una tabla de puntero virtual en cada instancia de objeto. –

0

Hay muchas variaciones para hacer programación OO en C. La forma en que prefiero hacerlo es definir una clase por archivo de encabezado. Verá un constructor new_testclass() que acaba de inicializar los punteros de función y devuelve un puntero a una clase/estructura asignada. También cualquier función toma puntero a la clase en el primer parámetro (algo que C++ hace, pero oculta).

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

A continuación, puede utilizarlo.

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

Por supuesto, hay varios aspectos importantes de la programación orientada a objetos perdidos aquí, 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.

Cuestiones relacionadas