英文原文: GENERAL ------- Use real tabs that equal 4 spaces. Use typically trailing braces everywhere (if, else, functions, structures, typedefs, class definitions, etc.) if ( x ) { } The else statement starts on the same line as the last closing brace. if ( x ) { } else { } Pad parenthesized expressions with spaces if ( x ) { } Instead of if (x) { } And x = ( y * 0.5f ); Instead of x = (y * 0.5f); Use precision specification for floating point values unless there is an explicit need for a double. float f = 0.5f; Instead of float f = 0.5; And float f = 1.0f; Instead of float f = 1.f; Function names start with an upper case: void Function( void ); In multi-word function names each word starts with an upper case: void ThisFunctionDoesSomething( void ); The standard header for functions is: /* ==================== FunctionName Description ==================== */ Variable names start with a lower case character. float x; In multi-word variable names the first word starts with a lower case character and each successive word starts with an upper case. float maxDistanceFromPlane; Typedef names use the same naming convention as variables, however they always end with "_t". typedef int fileHandle_t; Struct names use the same naming convention as variables, however they always end with "_t". struct renderEntity_t; Enum names use the same naming convention as variables, however they always end with "_t". The enum constants use all upper case characters. Multiple words are separated with an underscore. enum contact_t { CONTACT_NONE, CONTACT_EDGE, CONTACT_MODELVERTEX, CONTACT_TRMVERTEX }; Names of recursive functions end with "_r" void WalkBSP_r( int node ); Defined names use all upper case characters. Multiple words are separated with an underscore. #define SIDE_FRONT 0 Use ‘const’ as much as possible. Use: const int *p; // pointer to const int int * const p; // const pointer to int const int * const p; // const pointer to const int Don’t use: int const *p; CLASSES ------- The standard header for a class is: /* =============================================================================== Description =============================================================================== */ Class names start with "id" and each successive word starts with an upper case. class idVec3; Class variables have the same naming convention as variables. class idVec3 { float x; float y; float z; } Class methods have the same naming convention as functions. class idVec3 { float Length( void ) const; } Indent the names of class variables and class methods to make nice columns. The variable type or method return type is in the first column and the variable name or method name is in the second column. class idVec3 { float x; float y; float z; float Length( void ) const; const float * ToFloatPtr( void ) const; } The * of the pointer is in the first column because it improves readability when considered part of the type. Ording of class variables and methods should be as follows: 1. list of friend classes 2. public variables 3. public methods 4. protected variables 5. protected methods 6. private variables 7. private methods This allows the public interface to be easily found at the beginning of the class. Always make class methods ‘const’ when they do not modify any class variables. Avoid use of ‘const_cast’. When object is needed to be modified, but only const versions are accessible, create a function that clearly gives an editable version of the object. This keeps the control of the ‘const-ness’ in the hands of the object and not the user. Return ‘const’ objects unless the general usage of the object is to change its state. For example, media objects like idDecls should be const to a majority of the code, while idEntity objects tend to have their state modified by a variety of systems, and so are ok to leave non-const. Function overloading should be avoided in most cases. For example, instead of: const idAnim * GetAnim( int index ) const; const idAnim * GetAnim( const char *name ) const; const idAnim * GetAnim( float randomDiversity ) const; Use: const idAnim * GetAnimByIndex( int index ) const; const idAnim * GetAnimByName( const char *name ) const; const idAnim * GetRandomAnim( float randomDiversity ) const; Explicitly named functions tend to be less prone to programmer error and inadvertent calls to functions due to wrong data types being passed in as arguments. Example: Anim = GetAnim( 0 ); This could be meant as a call to get a random animation, but the compiler would interpret it as a call to get one by index. Overloading functions for the sake of adding ‘const’ accessible function is allowable: class idAnimatedEntity : public idEntity { idAnimator * GetAnimator( void ); const idAnimator * GetAnimator( void ) const; }; In this case, a const version of GetAnimator was provided in order to allow GetAnimator to be called from const functions. Since idAnimatedEntity is normally a non-const object, this is allowable. For a media type, which is normally const, operator overloading should be avoided: class idDeclMD5 : public idDecl { const idMD5Anim * GetAnim( animHandle_t handle ) const; idMD5Anim * GetEditableAnim( animHandle_t handle ); }; id Studio Names --------------- id<name>Dlg // dialog class id<name>Ctrl // dialog control class id<name>Frm // frame window id<name>View // view window id<name> // any other class FILE NAMES --------- Each class should be in a seperate source file unless it makes sense to group several smaller classes. The file name should be the same as the name of the class without the "id" prefix. (Upper/lower case is preserved.) class idWinding; files: Winding.cpp Winding.h When a class spans across multiple files these files have a name that starts with the name of the class without "id", followed by an underscore and a subsection name. class idRenderWorld; files: RenderWorld_load.cpp RenderWorld_demo.cpp RenderWorld_portals.cpp When a class is a public virtual interface to a subsystem the public interface is implemented in a header file with the name of the class without "id". The definition of the class that implements the subsystem is placed in a header file with the name of the class without "id" and ends with "_local.h". The implementation of the subsystem is placed in a cpp file with the name of the class without "id". class idRenderWorld; RenderWorld.h // public virtual idRenderWorld interface RenderWorld_local.h // definition of class idRenderWorldLocal RenderWorld.cpp // implementation of idRenderWorldLocal 翻譯如下: 常規約定 ------- 使用常規的tabs相當於4個空格。 通常,不管在哪裡,都使用尾隨的大括號(這些如:if、else、函數、結構體、定義類型、類定義等等) if ( x ) { } else語句在同一行上的最後一個大括號開始 if ( x ) { } else { } 在括號內,空一個空格後再使用表達式或者變量 if ( x ) { } 而不是 if (x) { } 還有就是 x = ( y * 0.5f ); 而不是 x = (y * 0.5f); 除非有一個明確的需要一個雙精度數值,否則使用浮點值的精度規范 float f =0.5f; 而不是 float f =0.5; 和 float f =1.0f; 而不是 float f =1.f; 函數名以大寫開始: void Function( void ); 在多詞函數名中,每個單詞以大寫開始: void ThisFunctionDoesSomething( void); 每個函數開頭寫的注釋的標准是: /* ==================== 函數名 說明 ==================== */ 變量名以小寫字母開頭。 float x; 在多字變量名稱的第一個字以小寫字符開始的,每一個連續的字開始用大寫。 float maxDistanceFromPlane; 定義類型名的命名規則和變量名的命名規則是一樣的,不過定義類型名是以“_t”結尾的。 typedef int fileHandle_t; 結構體名的命名規則和變量名的命名規則是一樣的,不過結構體名是以“_t”結尾的。 struct renderEntity_t; 枚舉名的命名規則和變量名的命名規則是一樣的,不過枚舉名是以“_t”結尾的。枚舉常量全部使用大寫字符。多個單詞的枚舉變量名使用下劃線將其分隔。 enum contact_t { CONTACT_NONE, CONTACT_EDGE, CONTACT_MODELVERTEX, CONTACT_TRMVERTEX }; 遞歸函數的名稱以“_r”結束 void WalkBSP_r( int node ); 宏定義名全部使用大寫字符。多個單詞的宏定義名使用下劃線將其分隔。 #defineSIDE_FRONT 0 盡可能地使用“const” 使用 const int*p; // pointer to const int int *const p; // const pointer to int const int * const p; // const pointer to const int 而不使用 int const*p; 類 ------- 每個類的開頭的標准是: /* =============================================================================== 描述 =============================================================================== */ 類名以“id”開始,後面的詞以一個大寫字符開始。 classidVec3; 類變量名的命名規則和變量名的命名規則是一樣的。 class idVec3 { float x; float y; float z; } 類方法的命名規則和函數的命名規則一樣。 class idVec3 { float Length( void ) const; } 為了制作整齊的列,我們會縮進類變量和類方法的變量。變量類型或方法的返回類型是在第一列中,變量名或方法名稱在第二列。 class idVec3 { float x; float y; float z; float Length( void ) const; constfloat * ToFloatPtr( void ) const; } *的指針在第一列,因為它當被認為是部分的類型從而提高了可讀性。 類的變量和方法的順序應該和下面的一樣: 1.列出友元類 2.公有變量 3.公有方法 4.保護變量 5.保護方法 6.私有變量 7.私有方法 這使得公共接口在類的開始很容易發現。 當類方法不修改任何類變量時,類方法總是定義為‘const’【常量方法】 避免使用“const_cast”。 當對象需要修改時,但只有常量的版本都可以訪問,創建一個函數,它清楚地提供了一個可編輯的對象版本。這保證了‘const-ness’的控制權在對象的手中,而不是在用戶的手中。 除非常規使用的對象是改變其狀態的,否則返回‘const’對象。例如,媒體對象,如idDecls在大部分的代碼中應該是const,而身份的對象根據各種系統修改狀態,並確定非const。 在大多數情況下,函數重載應該避免的。例如,而不是: constidAnim * GetAnim( int index ) const; constidAnim * GetAnim( const char *name )const; constidAnim * GetAnim( float randomDiversity) const; 而應使用: constidAnim * GetAnimByIndex( int index )const; constidAnim * GetAnimByName( const char *name) const; constidAnim * GetRandomAnim( floatrandomDiversity ) const; 命名准確、清晰的函數不容易造成編程者的錯誤,也不容易由於傳入錯誤數據類型的參數而造成不准確的函數調用。例如: Anim =GetAnim( 0 ); 這可能意味著調用得到一個隨機的動畫,但編譯器將其解釋為調用一個指數。 為了加入“常量”訪問功能的重載函數是允許的: class idAnimatedEntity : publicidEntity { idAnimator * GetAnimator( void ); const idAnimator * GetAnimator( void ) const; }; 在這種情況下,提供一個const的GetAnimator版本,以允許GetAnimator函數能夠被const函數調用。因為idAnimatedEntity通常是一個非常量對象,因此這是允許的。對於一個媒體類型,它通常是常量,操作符重載應該避免: class idDeclMD5 : public idDecl { const idMD5Anim * GetAnim( animHandle_t handle ) const; idMD5Anim * GetEditableAnim( animHandle_t handle ); }; id Studio Names --------------- id<name>Dlg // dialog class id<name>Ctrl // dialog control class id<name>Frm // frame window id<name>View //view window id<name> //any other class 文件名 --------- 除非是有意義的若干個更小的類,否則每個類應該是在一個單獨的源文件。文件名應該是和類的名稱沒有“id”前綴是一樣的。(大/小寫是保存。) class idWinding; files: Winding.cpp Winding.h 當一個類跨越多個文件,這些文件有一個名字,從類的名稱沒有“id”,其次是下劃線和分段的名字。 class idRenderWorld; files: RenderWorld_load.cpp RenderWorld_demo.cpp RenderWorld_portals.cpp When a class is a public virtual interface to a subsystem the public interface is implemented in a header file with the name of the class without "id". The definition of the class that implements the subsystem is placed in a header file with the name of the class without "id" and ends with "_local.h". The implementation of the subsystem is placed in a cpp file with the name of the class without "id". class idRenderWorld; RenderWorld.h // public virtual idRenderWorld interface RenderWorld_local.h // definition of class idRenderWorldLocal RenderWorld.cpp // implementation of idRenderWorldLocal