2010-07-19 8 views
12

¿Hay alguna ventaja en tener estructuras nunca definidas en C?Estructura nunca definida

Ejemplo de código fuente SQLite:

/* struct sqlite3_stmt is never defined */ 
typedef struct sqlite3_stmt sqlite3_stmt; 

Y el objeto se manipula este modo:

typedef struct Vdbe Vdbe; 
struct Vdbe { 
    /* lots of members */ 
}; 


int sqlite3_step(sqlite3_stmt *pStmt) { 
    Vdbe *v = (Vdbe*) pStmt; 
    /* do stuff with v... */ 
} 

¿Por qué no sólo tiene que utilizar un tipo abstracto de costumbre, con la estructura real definida en privado en foo.c fuente y un público typedef en el encabezado foo.h?

+1

No hay una buena razón. Pero mucha gente hace muchas cosas estúpidas en C, incluso en proyectos grandes y conocidos. –

+7

A R .: No llegarás muy lejos con ese tipo de actitud desdeñosa. sqlite es un conocido proyecto maduro que tiene fama por su calidad. Es probable que D. Richard Hipp sepa lo que está haciendo con el código. –

Respuesta

9

Para aclarar: Lo que estamos pidiendo es la razón por SQLite hace lo anterior en lugar de hacer esto:

Archivo de cabecera:

typedef struct sqlite3_stmt sqlite3_stmt; 

archivo C:

struct sqlite3_stmt { 
    /* lots of members */ 
}; 


int sqlite3_step(sqlite3_stmt *pStmt) { 
    /* do stuff with pStmt... */ 
} 

(Esto es la forma canónica del patrón de "puntero opaco" vinculado en la respuesta de KennyTM.)

El único bien La razón por la que puedo pensar por qué SQLite hace lo que hace es la siguiente:

El código del servidor, estoy especulando, vino antes de la API y usó el nombre Vdbe - el nombre probablemente significa algo relacionado con la implementación a lo largo del líneas de "entrada de la base de datos virtual" (adivinando salvajemente aquí).

Cuando llegó el momento de crear la API, alguien se dio cuenta de que el parámetro requerido por sqlite3_step era Vdbe pero que este no era exactamente un nombre que transmitiera mucho al usuario de la API. Por lo tanto, desde el punto de vista del usuario, un Vdbe se conoce como sqlite3_stmt.

El punto aquí es, entonces, para diferenciar entre dos vistas del mismo material: The back-end piensa en términos de Vdbe s (cualesquiera que sean), porque eso es un nombre que tenga sentido en el contexto de la aplicación. La API habla de sqlite3_stmt s porque es un nombre que tiene sentido en el contexto de la interfaz .

Editar: Como señala Amarghosh, ¿por qué no hacer esto para lograr el mismo efecto?

typedef struct Vdbe sqlite3_stmt; 

KennyTM points out a good possible reason (por favor, le votar, yo no quiero desviar su representante aquí): VDBE es sólo uno de varios backends posibles; la interfaz usa un sqlite3_stmt "genérico", que luego se convierte en lo que el programa de fondo utilice para implementarlo.

+4

Entonces, ¿por qué no solo 'typedef struct Vdbe sqlite3_stmt;' – Amarghosh

+0

Has acertado, esto es lo que estaba preguntando. Me gusta la idea de las dos vistas del mismo artículo. (y, dicho sea de paso, entiendo SQLite que VDBE significa "motor de base de datos virtual") – Axel

+0

@Amarghosh: Buen punto ... La respuesta editada de KennyTM proporciona una buena razón posible (que VDBE es solo uno de varios backends) –

15

Se define así para ocultar los detalles de implementación de sqlite3_stmt del usuario, evitando así que los estados internos se dañen. Ver Opaque pointer.

(Esto también obliga al usuario sólo para utilizar el tipo como un puntero ya que la estructura sqlite3_stmt sí tiene aplicación incompleta.)


Editar: VDBE (motor de base de datos virtual) es sólo "un" Back final de la API SQLite3. Creo que el back-end es modificable, por lo tanto, un sqlite3_stmt* no es necesariamente un Vdbe*. No exponiendo Vdbe* en la API porque los detalles de la parte posterior no deben exponerse.

+2

Aún así, en el ejemplo del artículo del puntero opaco, se define 'struct cat_t' ... ¿Se usa' struct sqlite3_stmt' solo para ocultar la implementación en 'struct Vdbe'? Entonces, ¿hay alguna razón para no usar el patrón de puntero opaco en 'Vdbe'? – Axel

+0

+1 "Creo que el back-end es modificable" ¡suena como una razón muy plausible! –