2

我正在努力解决设计问题,并且正在尝试为我的情况找到“最佳实践”的答案。

假设我有一个名为Logger.c(And Logger.h) 的文件,它负责在我的程序中记录操作。

我希望我的所有模块都引用记录器,所以每个模块都有一个 #include Logger.h.

假设我有一个名为NTFS.c负责与 NTFS FS 交互的模块,该模块具有在其标头中定义的特殊结构,例如:NTFS_Partition.

这是问题所在:

一方面,我希望记录器能够将 NTFS_Partition 的格式化表示打印到日志文件中,并且我必须#include NTFS.hLogger.h.

(Inside Logger.h)

#include NTFS_Partition
VOID Log_Partition(NTFS_Partition *part);

另一方面,我不确定 Logger 是否应该重新引用引用他的模块。

目前我看到两个主要选择:

1.Logger.h 包括 NTFS.h,NTFS.c 包括 Logger.h(这个工作)

2.我创建了一个名为 NTFS_Types.h 的新头文件,它将在所有模块之间共享,并且只包含 NTFS 结构的减速(如 NTFS_Partition)。

非常感谢,迈克尔。

4

2 回答 2

2

您可以创建一个共享标头,其中定义了所有结构。

// structs.h
struct NTFS_Partition { .. };
struct FAT32_Partition { .. };
struct FAT16_Partition { .. };

将其包含在logger.h.

// logger.h
#include "structs.h"
VOID Log_Partition(NTFS_Partition *part);
VOID Log_Partition(FAT32_Partition *part);
VOID Log_Partition(FAT16_Partition *part);

并包含logger.h在各种源文件中。

// NTFS.c
#include "logger.h"
// FAT32.c
#include "logger.h"
// FAT16.c
#include "logger.h"

在 C++ 中,最好在不同的头文件中保留不同的不相关类定义。但是在 C 中,将不同的结构定义放在单独的头文件中可能是一种矫枉过正的做法。

于 2013-09-06T00:46:33.917 回答
1

您是用 C 还是 C++ 编码并不完全清楚。我将假设 C(所以没有重载的函数名称等)。在我看来,您需要“转发声明”您的结构。在Logger.h中,你写:

#ifndef LOGGER_H_INCLUDED
#define LOGGER_H_INCLUDED

struct NTFS_Partition;     // No details - just the name (3 times)
struct FAT16_Partition;
struct FAT32_Partition;

...

void Log_NTFS_Partition(struct NTFS_Partition *part);
void Log_FAT16_Partition(struct FAT16_Partition *part);
void Log_FAT32_Partition(struct FAT32_Partition *part);

#endif // LOGGER_H_INCLUDED

这是一般客户(的Logger.h)需要知道的所有信息。

如果一个特定的客户端正在处理 NTFS 分区,那么它不仅会包括,Logger.h而且NTFS.h还会提供 的完整定义struct NTFS_Partition { ... };,因此客户端可以创建结构的实例并用数据填充它。当然,实现日志记录的代码 ,Logger.c也将包括Logger.hand NTFS.h(和FAT16.hand FAT32.h),因此它也可以引用结构的成员。

服务的标头(例如Logger.h)应提供服务客户端编译所需的最少信息量。实现文件可能需要更多信息,但可以从提供它的标头中收集额外信息。

使用该struct tag符号的一个优点恰恰是它可以根据需要经常重复,而不会弄乱任何东西。如果你没有 C11,你不能重复 a typedef,所以如果你写:

typedef struct NTFS_Partition NTFS_Partition;

您只能包含该行一次。困难在于确保它只定义一次。为此,您可能使用头FSTypes.h文件来定义文件系统typedefs,该文件系统受到头文件保护的适当保护,并包含在需要任何typedefs. 然后,您可以引用没有前面struct关键字的类型。

如果您使用 C++ 编写代码,typedef则不需要;struct NTFS_Partition;声明存在这样的结构类型,并声明NTFS_Partition为该类型的名称。如果您的代码是双语的,请使用typedef版本;它适用于 C 和 C++。

请注意,如果您的函数例如Log_NTFS_Partition()采用实际结构而不是指向结构的指针,那么您必须在范围内定义结构。但是,如果函数只接受指针,则前向声明就足够了。

于 2013-09-06T05:32:01.853 回答