Como puede ver, quiero separar lógicamente la tabla de la implementación del cursor. Además, quiero ocultar al usuario la información de la tabla y del cursor. Sin embargo, hacerlo generará el siguiente error del compilador
./table.h:10:1: error: unknown type name 'Cursor'
La solución alternativa es reenviar la declaración de estructura o colocar la declaración de estructura en los archivos de encabezado. Pero NO son muy elegantes.
O simplemente no sé cómo usar la declaración directa de una manera "mejor".
¿Hay alguna otra manera de lograr lo que estoy tratando de hacer aquí?
Cualquier ayuda será apreciada.
cursor.h
#ifndef CURSOR_H #define CURSOR_H #include "table.h" typedef struct Cursor_t Cursor; //struct data hiding //struct Table; //alternative solution: forward declaration //struct Table* cursor_get_table(Cursor* cursor); Table* cursor_get_table(Cursor* cursor); #endifcursor.c
#include "cursor.h" typedef struct Cursor_t { Table* table; } Cursor; //struct Table* cursor_get_table(Cursor* cursor) { //alternative solution Table* cursor_get_table(Cursor* cursor) { return cursor->table; //warning: incompatible pointer types returning 'Table *'... }mesa.h
#ifndef TABLE_H #define TABLE_H #include "cursor.h" typedef struct Table_t Table; //struct data hiding //struct Cursor; //alternative solution: forward declaration //struct Cursor* table_start(Table* table); Cursor* table_start(Table* table); //error: unknown type name 'Cursor' #endifmesa.c
#include "table.h" typedef struct Table_t { } Table; //struct Cursor* table_start(Table* table) { //alternative solution Cursor* table_start(Table* table) { return 0; }C Principal
#include <stdio.h> #include "cursor.h" #include "table.h" int main() { Table* table; Cursor* cursor; printf("hello world\n"); return 0; }Tenga en cuenta que main.c es solo un código de prueba. No estoy tratando de lograr nada significativo aquí.
Tiene una dependencia circular en sus archivos de encabezado, por lo que solo uno de ellos se incluye en el otro, según el archivo que esté compilando.
Ambos archivos de encabezado necesitan ver la declaración directa del tipo del otro, así que cree un tercer encabezado con los tipos e inclúyalo en los encabezados existentes.
tipos.h
#ifndef TYPES_H #define TYPES_H typedef struct Cursor_t Cursor; typedef struct Table_t Table; #endifcursor.h
#ifndef CURSOR_H #define CURSOR_H #include "types.h" Table* cursor_get_table(Cursor* cursor); #endiftabla.h:
#ifndef TABLE_H #define TABLE_H #include "types.h" Cursor* table_start(Table* table); #endif Sus archivos .c tendrían las definiciones de estructura, pero sin el typedef ya que ya existe.
Las declaraciones de estructura directa con el uso de punteros también son una forma de ocultar datos. cursor.c no podría tener acceso a Table interna y contener la definición del Cursor .
Esto permite cambios en la implementación sin volver a compilar los usos (mediante un archivo MAKE).
Es posible que necesite funciones solo entre cursor.c y table.c, pero eso podría incluso colocarse en un cursor_table.h o cualquier estilo que desee. Existen "clases" estrechamente acopladas.