匈牙利,我誤會你了

有寫過程式的人應該都會有聽過所謂的匈牙利命名法,這是由微軟的程式設計師 Charles Simonyi 所發明的,幾乎在所有程式語言的入門書都會提到。依照書中所寫,所謂的匈牙利命名法便是在變數前面加上該變數的型別,例如:

int iCount;
char szName[100];

整 數型別就加上個 "i";以 NULL 字元結尾的字串就加上個 "sz"。C 語言中的基本型別並不多,因此對於程式設計師來說,使用這個命名法也不會太麻煩。隨著 Windows 的普及,在 Win32 中大量導入 Handle 的概念,視窗有視窗的 handle(HWND),Process 有 Process 的 handle(HANDLE)。為了要區別這些變數,開始有人建議在這些變數也加上前綴字元,於是就出現這樣的變數:

HWND hwndMainWin;
HANDLE hProcess;

好吧,就算是再加入這幾種型別也還在程式設計師的記憶體範圍內,大家也都還能接受,於是匈牙利命名法著實風光了一陣子。然而隨著 C++ 的出現,匈牙利命名法受到史無前例的挑戰。
在 OOP 中,自訂型別是一項很重要的特徵。你可以將資料及處理邏輯封裝在一起,成為一種新的型別,並且可以跟基本的型別或其他自訂的型別作運算。一時間,大量的型 別冒了出來,突然間程式設計師不知道要如何來命名他的變數。像是一個用來封裝 Windows 基本控制項的 Button 類別,我們可能會這樣寫

CButton btnButton1;

高 明的程式設計師會用這個類別的縮寫來做前綴字元,這通常不會使用超過三個字。有些人看到這樣的命名法可能會覺得怪怪的,變數名稱 "Button1" 不就說明它是一個 Button 類別了嗎,就算不是直接從 CButton 來,我們也可以預期它的動作是和 CButton 一樣,那為什麼還要加上個前綴字元來減少鍵盤按鍵的壽命呢?
為了要讓這些人心服口服,因此我們不再使用像 Button1 這樣白痴的命名方式(然而幾乎所有的 RAID 工具都是產生這樣的名字),我們把 Button1 依照他的功能來命名。

CButton btnOk;
CListCtrl listFile;

因 此我們可以知道 btnOk 是個會產生 IDOK 訊息的 Button,而 listFile 則是個能顯示一堆檔案的列表元件。故事到此好像就風平浪靜,匈牙利命名法似乎也在 C++ 取得一片天。過了不久,就像國王的新衣故事中最後的小孩一樣,有人開始提出了質疑,為什麼不能用這樣的命名就好:

CButton OkBtn;
CListCtrl FileListCtrl;

雖然只是把前綴字元擺到後面去,但是閱讀起來似乎也還有那麼一點人性。
自 從我踏入 C++ 的領域後,對匈牙利命名法也開始感到有點感冒,覺得這樣子用好像有點多此一舉 ,但是在公司的 Coding Standard 中往往又強調這個部份,讓人不得不用。因為用起來不是很順手,再加上不喜歡遵守規定的天性,對匈牙利命名法總是不屑一顧。到目前為止,我最常用的前綴字元 只有 "g_"(用來表示全域變數)、"m_"(用來表示 class 的 member)。
直到從 Joel on Software 看到"讓錯的程式看得出錯"這篇文章才知道原來匈牙利命名法的原來意圖是要用來表示一個變數的用法,而不是用來表示該變數的型別。許多書上都誤會了他的用 法,以致於以訛傳訛,結果是大家都以為這樣的用法才是對的,即使是不順手,也因為大家都在用而不敢做聲,我想這也是一種盲從吧。

 



 編碼風格約定的目的是為了編寫出的代碼清晰和一致。Win32 中採用的是「匈牙利命名法」,這已經成為在 Win32 編程中通用的編碼慣例。它含有變數前綴符號,該符號給出了一個變數的建議類型。以下的前綴是共同的:

a Array 陣列
b BOOL (int) 布林變數
by Unsigned Char (byte) byte
c Char 字符
cb Count of bytes byte數量
cr Color reference value 顏色
cx Count of x (short) x 類型數量
dw DWORD (unsigned long) 雙字
f Flags (usually multiple bit values)多位標誌
fn Function 函數
g_ global 全域變數
h Handle 句柄
i Integer 整數
l Long 長整數
lp Long pointer 長指標
m_ Data member of a class 類別資料成員
n Short int 短整數
p Pointer 指標
s String 字串
sz Zero terminated String 零結束字串
tm Text metric 公制文字
u Unsigned int 無符號整數
ul Unsigned long (ULONG) 無符號長整數
w WORD (unsigned short) 字
x,y x, y coordinates (short) x,y 座標值

  這些約定可以相互結合,如:

pszMyString 指向一零結束字串的指標.
m_pszMyString 一個類的指向一零結束字串的指標

  其他約定還有:

CMyClass 前綴 'C' 代表一 C++ 類名.
COMyObjectClass 前綴 'CO' 代表一 COM 對象類名
CFMyClassFactory 前綴 'CF' 代表一 COM 類工廠名
IMyInterface 前綴 'I' 代表一 COM 接口的類名
CImpIMyInterface 前綴 'CImpI' 代表一 COM 接口實現的類名

/---------------------------------------------------------------------------------
變數名稱 = 屬性+類型+描述
屬性

* g_ 全域變數
* c_ 常數
* m_ 成員變數

類型

* n int
* l long
* sh short
* f float
* d double
* ld long double
* c char
* b boolean
* p pointer
* h handle

描述

* Custom 自訂
* Src 來源
* Dst 目的
* Tmp 暫時

範例 g_nCounter dAverage

arrow
arrow
    全站熱搜

    huenlil 發表在 痞客邦 留言(2) 人氣()