如何解决头文件之间的这种相互依赖关系?
How can I resolve this mutual dependency between header files?
请注意,有几个关于 SO 循环依赖的问题(包括我自己问过的一个),但我觉得 none 帮助我解决了这个特殊问题。
请考虑以下两个文件:
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 中解决此类问题的常用方法是什么?
请纯粹解决技术方面的问题,而不是软件设计方面的问题。
我想您可能会争辩说我在这里是在解决软件设计方面的问题,但我不知道如何在不稍微重构您的代码的情况下做到这一点。即,暂时避免使用 typedef。 (尽管我建议永久丢弃 typedef。)对于您的特定情况,table.h 不需要知道 ObjectString 是什么,因为它只使用指向它的指针。所以你可以简单地不在 table.h 中导入 "object.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
也许你可以这样做,将table.h和object.h放在一个名为both.h的文件中,不再需要table.h和object.h,只使用 both.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
请注意,有几个关于 SO 循环依赖的问题(包括我自己问过的一个),但我觉得 none 帮助我解决了这个特殊问题。
请考虑以下两个文件:
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 中解决此类问题的常用方法是什么?
请纯粹解决技术方面的问题,而不是软件设计方面的问题。
我想您可能会争辩说我在这里是在解决软件设计方面的问题,但我不知道如何在不稍微重构您的代码的情况下做到这一点。即,暂时避免使用 typedef。 (尽管我建议永久丢弃 typedef。)对于您的特定情况,table.h 不需要知道 ObjectString 是什么,因为它只使用指向它的指针。所以你可以简单地不在 table.h 中导入 "object.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
也许你可以这样做,将table.h和object.h放在一个名为both.h的文件中,不再需要table.h和object.h,只使用 both.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