我們知道 C/C++ 的 Header file 不適合在裡面宣告實體物件的。
因為做為一個 header file 可能會有很多程式檔含入(include)該 Header file。
如果你宣告了一個物件在裡面,編譯器會給你一個難堪的"重覆定義"的錯誤訊息。
通常的做法是,你應宣告全域物件在各自所屬的程式檔中,而其它要用到該物件的程式則宣告該全域物件為 external 即可。
現在的問題是,若有一個全域物件有許多的程式檔要用到,
例如二十個檔案要使用,那麼要二十個檔案都要寫 external 宣告是非常麻煩的事!
如果編譯器能聰明一點,在 Header file 宣告了全域變數,它實際只產一個物件,
而其它所有含入這 Header file 的程式就全部以 external 在參考那唯一產生的物件,豈不佳妙!?
其實也真的有這樣的編譯器來幫忙"懶惰"的程式師(如 MS C 5.x 以前的版本)。
但這是不正規的編譯器,也會延生其它問題(例如程員把原本應為兩個不同的物件卻寫成了同名)。
所以絕大部份的編譯器是不允許你宣告物件在 Header file 給兩個以上的程式檔含入的。
那麼有沒有兩全其美的方法?答案是肯定的,就是"自力救濟法"!
方法解釋起來還有點傷腦筋,好在程式不難,就用舉例來說明囉:
假設有一個 MyLib.C 的程式寫了一些 function 給其它的程式檔呼叫使用,
而 MyLib.c 有一個全域變數叫 LastErrorNo,是做為有錯誤發生時,其它程式可以檢知發生了什麼事。
那麼 MyLib 想當然會有一個 Header file 定義了所有的 functions (名字就取為 MyLib.H)。
下面示範如何把 LastErrorNo 這個物件宣告在 MyLib.H 裡面。
//程式檔 MyLib.C
code:--------------------------------------------------------------------------------
#define MyLib_C
#include ".........."
#include "MyLib.H"
#undef  MyLib_C
..........
int function1(...)
{
    ..........
}
int function2(...)
{
    ..........
}
..........
--------------------------------------------------------------------------------
//其它含入 MyLib.H 的程式檔
code:--------------------------------------------------------------------------------
#include ".........."
#include "MyLib.H"
#include ".........."
..........
--------------------------------------------------------------------------------
//Header file MyLib.H
code:--------------------------------------------------------------------------------
..........
int function1(...);
int function2(...);
#ifdef MyLib_C
    #define AUTOEXT
#else //MyLib_C
    #define AUTOEXT  extern
#endif //MyLib_C
AUTOEXT  int LastErrorNo;
..........
#undef AUTOEXT
--------------------------------------------------------------------------------

這樣子 MyLib.C 本身和其它用到 MyLib.C 全域物件的程式檔都可以放心的含入 MyLib.H 了!

ANSI C 本來就規定 extern int LastErrorNo;
宣告之後可以出現 lastErrorNo 的定義, 所以你可以把
code:--------------------------------------------------------------------------------
extern int LastErrorNo;
--------------------------------------------------------------------------------
寫在 MyLib.h,在任何需要 MyLib 的本文檔 include MyLib.h,把 LastErrorNo 的定義寫在 MyLib.c 檔即可。
當然 MyLib.c 是一定會 include MyLib.h 的,於是 LastErrorNo 的宣告和定義會出現在同一個本文檔中,
但這是正規的 ANSI C 寫法,這樣本來就是符合惟一定義的規則。

把這一行:
code:--------------------------------------------------------------------------------
int LastErrorNo;
--------------------------------------------------------------------------------
寫在 MyLib.c 檔中.

Posted by BB at 痞客邦 PIXNET 留言(0) 引用(0) 人氣()