作者sunneo (艾斯寇德)
看板C_and_CPP
标题Re: [问题] .h宣告和定义分开的理由
时间Tue Apr 7 12:13:06 2009
※ 引述《godman362 (Shizuru)》之铭言:
: 小弟写程式也三年了
: 最近开始迈入小型的专案开发
: 但是我看了很多专案的程式码
: 大多都是将.h档的定义和宣告分开来放
: 我看过较多的说法是说不想将实作公开出来
: 但是我觉得这个说法似乎有些微的牵强
: 所以想请问一下各位先进,真正分开做的理由是甚麽?
: 还请各位指点一番。
有时候是因为实做的各个c/cpp档案里面可以存在static function(private function)
在有些时候,你不希望使用者直接修改你的变数内容或者结构体资讯时,你会把
结构体包成Handle (void*),这可以达成encapulation的效果。
将定义跟宣告分开,除了意外的你得到了一个附加的api,也可以免除维护上的困难,
(不管你有没有得到一个附加的api,函式说明还是以document输出的好。)
但最主要克服的还是在linker上的工作,如果你的实作不是inline且不是template
更不是class的implicit inline,那麽你就会在linker阶段碰上问题,
今天你在cpp 1里面因为header得到了global var A,cpp 1被编译为obj1
cpp2经由header得到了A的实体,
所以也来了个global var A,而你的专案需求是这两个obj要结合成一个档案
这时候就出现了重复定义的情况。
发布成dll的时候,差别就是你一定要把实作跟宣告分开,且要发布的进入点如果不是
inline/template,那就要用__declspec(dllexport) 修饰,在释出档要把header的
dllexport改为dllimport。
比如你在建立一个dll专案时会出现
#if BUILDING_DLL
# define DLLAPI __declspec(dllexport)
#else
# define DLLAPI __declspec(dllimport)
#endif
发布的格式如
DLLAPI RET_T FunctionName();
struct DLLAPI StructName{
...
};
class DLLAPI ClassName{
...
};
typedef,enum 的型别就不用了,这是compile阶段的。
全域变数
extern DLLAPI TYPE VARNAME;
假使全域变数是一个function pointer时也要汇出
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 61.227.112.207
1F:→ Bencrie:其实header本来就是为了分档用。把一个大程式拆成很多个 04/07 12:35
2F:→ Bencrie:source编译成很多个object,最後才全部连结起来。 04/07 12:36
3F:→ Bencrie:如果不分档,那麽每次改一点东西就要花很多时间重编译。 04/07 12:37
4F:→ Bencrie:而分档过的程式则可以针对被改过的source file重新编译 04/07 12:38
5F:→ Bencrie:成object然後再跟之前没动到的object做连结,省下不必要 04/07 12:39
6F:→ Bencrie:的编译时间。 04/07 12:39
7F:→ sunneo:原来如此 感谢楼上的说明 <(_ _)>04/07 12:38
※ 编辑: sunneo 来自: 61.227.112.207 (04/07 12:45)