Как я могу решить эту взаимную зависимость между заголовочными файлами? - PullRequest
0 голосов
/ 04 мая 2019

Обратите внимание, что есть несколько вопросов, касающихся циклических зависимостей от SO (включая тот, который я задавал себе), но я чувствую, что ни один из них не помог мне с этой конкретной проблемой.

Пожалуйста, рассмотрите два следующих файла:

table.h

#ifndef s_table_h
#define s_table_h

#include "value.h"
#include "object.h"

typedef struct {
    ObjectString* key;
    Value value;
} Entry;

typedef struct {
    int capacity;
    int count;
    Entry* entries;
} Table;

void initTable(Table* table);
void setTable(Table* table, ObjectString* key, Value value);
bool getTable(Table* table, ObjectString* key, Value* out);

#endif

object.h

#ifndef s_object_h
#define s_object_h

#include "common.h"
#include "table.h"

typedef enum {
    OBJECT_STRING
} ObjectType;

typedef struct {
    ObjectType type;
    Table attributes;
} Object;

typedef struct {
    Object base;
    char* chars;
    int length;
} ObjectString;

bool stringsEqual(ObjectString* a, ObjectString* b);

#endif

Как видите, эти два зависят друг от друга: table.h нужен ObjectString*, а object.h нужен бетон Table. Оба соответствующих файла реализации .c обращаются к конкретным членам ObjectString* и Table соответственно.

Каков рекомендуемый способ решения этой проблемы? И вообще, каков будет общий подход к таким проблемам в C?

Пожалуйста, обращайтесь исключительно к техническому аспекту, а не к программному.

Ответы [ 2 ]

1 голос
/ 04 мая 2019

Полагаю, вы могли бы поспорить, что я рассматриваю здесь аспект разработки программного обеспечения, но я не знаю, как это сделать без небольшого рефакторинга вашего кода.А именно, временно избегая typedef.(Хотя я бы посоветовал сбросить typedef навсегда.) Для вашего конкретного случая table.h не нужно знать, что такое ObjectString, поскольку он использует только указатель на него.Таким образом, вы можете просто не импортировать "object.h" в table.h, а вместо этого написать:

object.h:

#ifndef s_object_h
#define s_object_h

#include "common.h"
#include "table.h"

typedef enum {
    OBJECT_STRING
} ObjectType;

typedef struct {
    ObjectType type;
    Table attributes;
} Object;

struct ObjectString {
    Object base;
    char* chars;
    int length;
};

typedef struct ObjectString ObjectString;

bool stringsEqual(ObjectString* a, ObjectString* b);

#endif

table.h:

#ifndef s_table_h
#define s_table_h

#include "value.h"

typedef struct {
    struct ObjectString* key;
    Value value;
} Entry;

typedef struct {
    int capacity;
    int count;
    Entry* entries;
} Table;

void initTable(Table* table);
void setTable(Table* table, struct ObjectString* key, Value value);
bool getTable(Table* table, struct ObjectString* key, Value* out);

#endif
0 голосов
/ 04 мая 2019

Может быть, вы можете сделать это следующим образом, поместите table.h и object.h вместе в один файл с именем both.h, больше не нужно table.h и object.h, используйте только оба .h:

#ifndef s_table_h
#define s_table_h

#include "value.h"
#include "common.h"

//#include "object.h"
//#include "table.h"


typedef struct A ObjectString;      // add

typedef struct {
    ObjectString* key;
    Value value;
} Entry;

typedef struct {
    int capacity;
    int count;
    Entry* entries;
} Table;





typedef enum {
    OBJECT_STRING
} ObjectType;

typedef struct {
    ObjectType type;
    Table attributes;
} Object;

typedef struct A {     // modify to typedef struct A
    Object base;
    char* chars;
    int length;
} ObjectString;

bool stringsEqual(ObjectString* a, ObjectString* b);
void initTable(Table* table);
void setTable(Table* table, ObjectString* key, Value value);
bool getTable(Table* table, ObjectString* key, Value* out);

#endif
...