Here are some suggestions for a naming convention. These help identify the variables' usage and type and thus reduce coding errors. This is an abridged Hungarian notation:
[<scope>_]<type><name>
Prefix
|
Variable scope
|
m
|
Instance class members
|
c
|
Static class member (including constants)
|
g
|
Global static variable
|
<empty>
|
local variable or struct or public class member
|
<type>
Prefix
|
Data Type
|
b
|
Boolean
|
by
|
byte or unsigned char
|
cx/cy
|
short used as size
|
d
|
double
|
dw
|
DWORD, double word or unsigned long
|
f
|
float
|
fn
|
function
|
h
|
handle
|
i
|
int (integer)
|
ip
|
smart pointer
|
l
|
long
|
p
|
a pointer
|
s
|
string
|
sz
|
ASCIIZ null-terminated string
|
w
|
WORD unsigned int
|
x,y
|
short used a coordinates
|
<name> describes how the variable is used or what it contains. The <scope> and <type> portions should always be lowercase, and the <name> should use mixed case:
Variable Name
|
Description
|
m_hWnd
|
a handle to HWND
|
ipEnvelope
|
a smart pointer to a COM interface
|
m_pUnkOuter
|
a pointer to an object
|
c_isLoaded
|
a static class member
|
g_pWindowList
|
a global pointer to an object
|
Type Names
All type names (class, struct, enum, and typedef) begin with an uppercase letter and use mixed case for the rest of the name:
class Foo : public CObject { . . .};
struct Bar { . . .};
enum ShapeType { . . . };
typedef int* FooInt;
struct Bar { . . .};
enum ShapeType { . . . };
typedef int* FooInt;
Typedefs for function pointers (callbacks) append Proc to the end of their names.
typedef void (*FooProgressProc)(int step);
Enumeration values all begin with a lowercase string that identifies the project; in the case of ArcObjects, this is esri, and each string occurs on a separate line:
typedef enum esriQuuxness
{
esriQLow,
esriQMedium,
esriQHigh
} esriQuuxness;
{
esriQLow,
esriQMedium,
esriQHigh
} esriQuuxness;
Function Names
Name functions using the following conventions:
For simple accessor and mutator functions, use Get<Property> and Set<Property>:
int GetSize();
void SetSize(int size);
void SetSize(int size);
If the client is providing storage for the result, use Query<Property>:
void QuerySize(int& size);
For state functions, use Set<State>, and Is<State> or Can<State>:
bool IsFileDirty();
void SetFileDirty(bool dirty);
bool CanConnect();
void SetFileDirty(bool dirty);
bool CanConnect();
Where the semantics of an operation are obvious from the types of arguments, leave type names out of the function names.
Instead of
AddDatabase(Database& db);
consider using
Add(Database& db);
Instead of
ConvertFoo2Bar(Foo* foo, Bar* bar);
consider using
Convert(Foo* foo, Bar* bar)
If a client relinquishes ownership of some data to an object, use Give<Property>. If an object relinquishes ownership of some data to a client, use Take<Property>:
void GiveGraphic(Graphic* graphic);
Graphic* TakeGraphic(int itemNum);
Graphic* TakeGraphic(int itemNum);
Use function overloading when a particular operation works with different argument types:
void Append(const CString& text);
void Append(int number);
void Append(int number);
Argument names
Use descriptive argument names in function declarations. The argument name should clearly indicate what purpose the argument serves:
bool Send(int messageID, const char* address, const char* message);