2009-06-03 13 views
9

Como programador de C++, tenemos que tratar con los conceptos y la relación de los conceptos relacionados con antes de implementarlos en las clases.¿Cómo debería un programador de C++ diseñar software en C?

Sin embargo, ¿cómo diseñar un software en lenguajes de procedimiento como C? ¿Cómo puedo manejar los conceptos sin la ayuda de la clase en C++?

relacionadas:

+0

Dupe of http://stackoverflow.com/questions/925754/resources-for-learning-c-program-design –

+1

Eso es preguntar acerca de los recursos, no las técnicas como aquí. –

Respuesta

31

Si está familiarizado con C++, puede considerar crear una estructura de datos en cualquier lugar donde crearía una clase, y crear funciones similares a los métodos de clase que normalmente crearía, con el primer parámetro aceptando un puntero a esa estructura .

+9

+1: solo porque C no tenga objetos no significa que aún no pueda usar métodos orientados a objetos (especialmente encapsulación) en C. Incluso es posible un tipo de polimorfismo. Solo mira el uso de HANDLE en la API de Win32. –

+0

+1, pero diré que hay diferencias significativas, como tener la manualmente llamada destructores –

+0

Mientras aprendía C++, me di cuenta de que debería haber estado haciendo esto todo el tiempo en C. Leter, la API de Windows solo confirmó esta línea de pensamiento. ... gracias por el voto popular. ;-) –

8

En un lenguaje orientado a objetos que se acostumbre a pensar en los objetos de datos primero, y luego pensar en qué métodos o comportamientos que desea aplicar a esos objetos. Ayuda en la programación de procedimientos para pensar en sus estructuras de datos por separado de las funciones que actúan sobre ellos.

6

También puede echar un vistazo a Glib/GObject, que proporcionan un mecanismo de clase para el lenguaje C. Es utilizado por muchos proyectos y es bastante poderoso y probado en gran medida.

2

Continuar pensando en términos de clases y las interfaces proporcionadas por las clases. Una clase de C++ se correlacionará con una estructura C. Las funciones miembro de clase se convierten en funciones C regulares. Proporcione un encabezado que declare la interfaz externa a la 'clase'. Acepte que algunas partes de C++ no están disponibles en C - espacios de nombres, excepciones (y, por supuesto, clases).

6

Es completamente posible llevar los principios de diseño OOP a 'C'. Te falta algo del azúcar sintáctico, pero al final del día todo son solo estructuras, funciones y punteros.

Tome un vistazo a glib, gtk y gts de buenos ejemplos de estilo de codificación programación orientada a objetos en C

6

Utilice únicamente descomposición funcional si el problema que está resolviendo mapas bien a ella.

Recuerde que los sistemas operativos, las GUI y otros sistemas no procesales controlados por eventos se escribieron en C mucho antes de que aparecieran los objetivos C y C++. C no es Cobol.

Antes de aprender C++, escribí una GUI basada en eventos en C utilizando matrices de indicadores de función. La encapsulación fue fácil, no hice ningún intento de polimorfismo, algunas relaciones se basaban en estándares de codificación y convenciones de nomenclatura, ya que los espacios de nombres y los objetos no estaban disponibles. Incorporó un analizador verdadero, recursivo ya que aún no había tomado la clase de Compilador en Uni. Y sí, todo encajaba en 640K, pero usé superposiciones.

Algunas personas intentan improvisar pseudoobjetos usando punteros a funciones en Structs. No veo el punto. En cierto punto, debes aceptar el hecho de que no estás usando C++.

2

Con lenguajes orientados a objetos, como C++, el problema se divide en objetos, como su nombre lo indica. Con los lenguajes de procedimiento, desea utilizar la descomposición funcional, donde el problema se divide en tareas y cada tarea en subtareas, y así sucesivamente ...

0

Aquí es cómo puede obtener la herencia simple:

struct Base { 
int a; 
};  
struct MyStruct { 
    Base parent; 
    int b; 
}; 

struct MyStruct myStruct; 
struct Base *base = (struct Base *) &myStruct; 
printf("%d\n", base->a); 
aFunctionExpectingBase(base); 

Esto imita GObject. Puede hacer otros trucos que hacen, por ejemplo: en cada estructura similar a un objeto, puede ser conveniente incluir un padre común de primer nivel. Podría proporcionar una funcionalidad básica de su sistema de objetos C.

2

En C, los programadores a menudo imitan la idea de una clase separando funciones relacionadas en archivos .h/.c y tratándolas como una clase. Colocar variables en el ámbito local puede considerarse 'privado'.

0

Use Functional Decomposition.

Descomposición funcional es un método de arriba hacia abajo para diseñar un programa de forma sistemática. La idea es descomponer el problema en sus subtareas, descomponiendo las subtareas a su vez hasta que los detalles sean lo suficientemente buenos como para traducirlos a un lenguaje de programación. Depende del diseñador elegir cómo deshacer el problema.

+1

¡No desestime esta pregunta simplemente porque no menciona OO! – Arafangion

3

No hay absolutamente nada que le impida usar todas las mismas técnicas que utiliza en C++ en C. El diseño orientado a objetos, incluida la herencia múltiple es lo suficientemente simple de lograr. Incluso puede obtener la programación de plantillas con un poco de inteligencia macro. Lo único es que el programa C resultante no será tan elegante como el C++ equivalente, porque el lenguaje no te ayuda mucho con estos conceptos.

Existen solo dos características que ofrece el lenguaje C++ que será difícil de evitar. Primero, la ayuda que C++ ofrece para la especialización de plantillas. Probablemente tendrá que administrar el código objeto de la plantilla con más cuidado de lo que haría con C++. Sin embargo, este es un aspecto bastante fácil de la metaprogramación de plantillas en C, ya que obtener macros para hacer lo correcto es mucho más complicado.

El problema más grande es que el lenguaje no finaliza automáticamente instancias de clase cuando salen del alcance, que es el gran concepto de C++. Tendrá que administrar meticulosamente los recursos en C, donde C++ haría todo el trabajo automáticamente en el momento correcto.

+1

+1 - solo para tener en cuenta que los primeros compiladores de C++ fueron en realidad traductores a C puro y están disponibles incluso hoy en día. – Zyx

1

Puede imitar la clase C++ y los métodos con C struct y los punteros a las funciones. Es un poco doloroso (todo se hace detrás de la escena en C++) pero proporciona una muy buena flexibilidad para su programa.

4

Ha recibido muchas propuestas sobre cómo implementar conceptos orientados a objetos en C, pero a menos que el dominio problemático lo haga altamente deseable (por ejemplo, programación GUI), debería IMO usar C y otros lenguajes de procedimiento de forma procedimental . OOP es IMO no inherentemente mejor para todos los escenarios.

Es posible que desee echar un vistazo al método "bueno viejo" structured analysis para la fase de análisis/diseño de su proyecto.

1

Bueno, todavía se puede diseñar buenos tipos abstractos de datos en C. Se empieza por typedef ing una estructura, proporcionando crear/destruir funciones, y luego otros setters/getters/hacedores de operar en esa estructura:

typedef struct { 
    /* maintain private state here */ 
    unsigned int x; 
    char *y; 

} mytype_t; 

/** Creates a new mytype... */ 
mytype_t *mytype_create(unsigned int x, char *y); 

/** Destroys a mytype, freeing all associated memory. */ 
void mytype_destroy(mytype_t *t); 

/** Does something to mytype... */ 
void mytype_do_something(mytype_t *t, int bla); 

Así que implemente estas funciones y mantenga su estado accediendo a los miembros 'privados' en la estructura, cuyo puntero se pasa a cada función.

A continuación, puede utilizar esta interfaz de la siguiente manera:

 
mytype_t* t = mytype_create(foo, bar); 
mytype_do_something(t); 

/* do some other stuff */ 

mytype_destroy(t); 

El punto importante es la siguiente: tan pronto como se typedef struct, los usuarios del tipo no se les permite acceder a sus miembros. Solo deberían hablar con él a través de la interfaz pública/funciones definidas para él.

Veo las estructuras de destrucción de tipos de personas solo para evitar tener que escribir 'struct' por todas partes, pero hay que considerar que definen un nuevo tipo abstracto, cuya implementación interna puede cambiar. Seguro que un usuario del tipo puede bucear y acceder a los miembros, pero eso es algo malo de hacer. Una estructura typedef significa "privado, ¡fuera!". Esto es información básica escondida.

Tiendo a usar también un estilo de prefijo para nombrar, es decir, mytype_verb. Esto ayuda con intellisense porque puedo escribir mytype_ y obtener una lista de funciones para ese tipo. También ayuda con los conflictos de nombres ya que no hay soporte de espacio de nombres en C, por lo que verá que la mayoría de las bibliotecas C usan prefijos (como sqlite3_) frente a todo lo que definen.

+0

Tendría realmente mytype_destroy (mytype_t (ptr) t) toma un mytype_t (ptr) (ptr) para que pueda establecerlo en NULL para evitar tener que anular manualmente después de cada llamada. –

Cuestiones relacionadas