一个项目会切割成很多模块,模块与模块之前的联系,需要通过头文件来联系起来,这就是为什么先设计头文件,再实现.c的原因
总结一下编码历程:
1,刚开始学C,把各种结构体,函数声明放一个.h中;
2,接着发现,要学会隐藏,把结构体,内部函数的声明放模块使用的.h,把之前一个大的.h切割成N多的模块.h
3,最后发现,把结构体,内部函数声明全部放模块.c中(如果没有依赖的话,甚至一个内部函数声明都不用写);
模块.h只放外部接口函数声明,其它全部隐藏起来,不对别的模块开放
一个模块A会用到模块B的引用,通常的设计如下:
///////////////////////
module_b.h:
#ifndef _MODULE_B_H_
#define _MODULE_B_H_
struct B_s
{
int a;
int b;
};
typedef struct B_s B_t;
int func_b();
#endif
///////////////////////
module_a.h:
#ifndef _MODULE_A_H_
#define _MODULE_A_H_
#include "module_b.h"//不好的设计
struct A_s;
typedef struct A_s A_t;
int func_a(B_t *_data);
#endif
///////////////////////
实际上A模块只是用到B模块的方法,现在却调用了module_b.h,B模块的外部接口函数func_b暴露给A模块了,
把结构体放到module_b.c中去,头文件中只做一个不完整的定义,修改后的设计:
///////////////////////
module_b.h:
#ifndef _MODULE_B_H_
#define _MODULE_B_H_
struct B_s;//这里是个不完整定义
typedef struct B_s B_t;
int func_b();
#endif
///////////////////////
module_a.h:
#ifndef _MODULE_A_H_
#define _MODULE_A_H_
struct B_s;//这里是个不完整定义
struct A_s;
typedef struct A_s A_t;
int func_a(struct B_s *_data);
#endif
///////////////////////
这样做的原则就是,头文件体积尽量下,不开放给模块的信息,都不要写到头文件.h中
另外,typedef的使用,到底要不要?许多大牛们反对利用它,(的确上面代码重新设计后就必须采用struct B_s结构,如果采用B_t,会有所担心module_a.h和module_b.h被同一个引用,最终导致重复定义,大牛们说得很有道理),但是利用它的确可以省去写N多union,struct的麻烦,而且***_t只是在自己的模块中用,至于其他模块的头文件中的引用,没办法,还是老实的用union,struct
log4c中就是这样用的
另外,如果模块A和模块B相互引用呢?这就相当于C++中的friend
总结一下编码历程:
1,刚开始学C,把各种结构体,函数声明放一个.h中;
2,接着发现,要学会隐藏,把结构体,内部函数的声明放模块使用的.h,把之前一个大的.h切割成N多的模块.h
3,最后发现,把结构体,内部函数声明全部放模块.c中(如果没有依赖的话,甚至一个内部函数声明都不用写);
模块.h只放外部接口函数声明,其它全部隐藏起来,不对别的模块开放
一个模块A会用到模块B的引用,通常的设计如下:
///////////////////////
module_b.h:
#ifndef _MODULE_B_H_
#define _MODULE_B_H_
struct B_s
{
int a;
int b;
};
typedef struct B_s B_t;
int func_b();
#endif
///////////////////////
module_a.h:
#ifndef _MODULE_A_H_
#define _MODULE_A_H_
#include "module_b.h"//不好的设计
struct A_s;
typedef struct A_s A_t;
int func_a(B_t *_data);
#endif
///////////////////////
实际上A模块只是用到B模块的方法,现在却调用了module_b.h,B模块的外部接口函数func_b暴露给A模块了,
把结构体放到module_b.c中去,头文件中只做一个不完整的定义,修改后的设计:
///////////////////////
module_b.h:
#ifndef _MODULE_B_H_
#define _MODULE_B_H_
struct B_s;//这里是个不完整定义
typedef struct B_s B_t;
int func_b();
#endif
///////////////////////
module_a.h:
#ifndef _MODULE_A_H_
#define _MODULE_A_H_
struct B_s;//这里是个不完整定义
struct A_s;
typedef struct A_s A_t;
int func_a(struct B_s *_data);
#endif
///////////////////////
这样做的原则就是,头文件体积尽量下,不开放给模块的信息,都不要写到头文件.h中
另外,typedef的使用,到底要不要?许多大牛们反对利用它,(的确上面代码重新设计后就必须采用struct B_s结构,如果采用B_t,会有所担心module_a.h和module_b.h被同一个引用,最终导致重复定义,大牛们说得很有道理),但是利用它的确可以省去写N多union,struct的麻烦,而且***_t只是在自己的模块中用,至于其他模块的头文件中的引用,没办法,还是老实的用union,struct
log4c中就是这样用的
另外,如果模块A和模块B相互引用呢?这就相当于C++中的friend