C++ Coding Style
Low Zhen Lin <[email protected]> Sun, 21 Dec 2003 00:03:55 +0800
| Newsgroups | gmane.linux.zynot.general,gmane.linux.zynot.devel |
|---|---|
| Message-ID | <[email protected]> |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Since we are about to begin coding, I thought it might be wise to
declare the style conventions.
Here are mine:
4 spaces per tab.
'{' on a new line, flush with the previous line:
~ int main()
~ {
... except when hugged:
~ } else {
~ } else if ... {
~ } catch (...) {
... or in small initialisers:
~ int arr[4] = { 0, 1, 2, 3 };
~ uuid id = { 0xDEADBEEF, 0x0F00, 0x0BA2, 0x1337, 0xBABA, 0xBEEFDEAD };
... where the insides are padded with one space on both ends.
'(' immediately after function names and constructors (and macros -
macros REQUIRE this rule):
~ int main(int argc, const char* argv[]);
~ std::string s("Hello World!");
~ exit(-1);
~ sizeof(int) // sizeof is function-like.
... one space after branch control:
~ if (i < 0)
~ while (true)
... none in these:
~ return 0;
~ throw *new ArrayIndexOutOfBoundsException;
~ a = new Object;
'*' attached to typename, no spaces in declaration:
~ const char* cstring;
~ int (*pfunc)(int, int);
... one space after for casting:
~ (int *)malloc(sizeof(int[128]));
~ (void *)main;
... no spaces in between '*':
~ const char** argv;
~ (void **)vtable
... no spaces after for dereferencing:
~ *(array_start + index);
~ return (*a < *b);
... none for invoking functions:
~ pfunc(); // Not compatible with MSVC++
... function pointers:
~ RetType (*TypeName)(ParamType, ParamType)
'[]' attached to identifier, no spaces, always:
~ int array[16];
~ int matrix[8][8];
~ int 3dSpace[4][4][4];
'<' after 'template', space in between:
~ template <typename T> T* allocate();
Even if it is 'template <>', retain it:
~ template <> int getFib<1>() { return 1; }
~ template <> int getFib<0>() { return 0; }
'<' after template name, no space in between:
~ template <int N> int getFib() { return getFib<N-1>() +
getFib<N-2>(); }
CamelCasing for type names, smallFirst for instance names:
~ RadioButton radioButton;
~ void onClick(double, double);
~ // onClick is an instance of void (*)(double, double)
Space after ',', always:
~ int arr[] = { 0, 1, 2, 3 };
~ printf("%s", cstring);
Labels at previous indent level:
~ int main()
~ {
~ int i = 0;
~ LoopTop:
~ cout << "i = " << i << endl;
~ i++;
~ if (i < 16)
~ goto LoopTop;
~ return 0;
~ }
... except when the label marks off sections of code,
~ has special meaning,
~ or is at the top of a block:
~ int main()
~ {
~ Top:
~ cout << "At Top!" << endl;
~ Bottom:
~ cout << "At Bottom!" << endl;
~ return 0;
~ }
~ switch (choice)
~ {
~ case 0:
~ cout << "This menu system is a figment of your
imagination." << endl;
~ break;
~ case 1:
~ case 2:
~ case 3:
~ case 4:
~ case 5:
~ cout << "Pick a bigger number, nitwit!" << endl;
~ break;
~ case 6:
~ case 7:
~ case 8:
~ case 9:
~ cout << "You have selected " << choice << ". Have a nice
day." << endl;
~ break;
~ default:
~ cout << "Hmm, you have a queer number pad." << endl;
~ }
~ class Object
~ {
~ public:
~ explicit Object();
~ protected:
~ unsigned int refCount;
~ private:
~ Object(Object&) { }
~ };
When there is only one statement where there is normally a block, put
the statement on the same line as the block-preceding line:
~ switch (choice)
~ {
~ case 5: cout << "Hello!" << endl;
~ case 4: cout << "Hello!" << endl;
~ case 3: cout << "Hello!" << endl;
~ case 2: cout << "Hello!" << endl;
~ case 1: cout << "Hello!" << endl;
~ case 0: break;
~ default:
~ for (int i = 0; i < choice; i++) cout << "Hello!" << endl;
~ break;
~ }
~ if (o.isa(Class(String)) cout << "I got a String!" << endl;
~ else if (o.isa(Class(Number)) cout << "I got a Number!" << endl;
~ else if (o.isa(Class(Object)) cout << "I got an Object!" << endl;
~ else cout << "I got something wierd." << endl;
Note that the 'if' lines up. When feasible, line up code to be neater:
~ int i = 0;
~ char c = '\0';
~ double d = 0.0;
~ void* p = 0;
Local variable declaration at the top of the function body, split into
groups, seperate groups by a blank line:
~ int arr[128] = { 0 };
~ int index = 0;
~ // BLANK LINE
~ char string[] = "String";
~ char* pChar = string;
~ // BLANK LINE
~ node* rootNode = tree.getRoot();
~ node* parentNode = 0;
~ node* currentNode = root;
Prefer inline functions or templates to macros for code.
Prefer macros to inline functions or templates for simple expressions.
Always use inline functions and/or templates when parameters are
evaluated more than once.
Avoid 'using namespace' statements in headers.
'.c++' for C++ source code. 'cpp' is the C preprocessor, damnit! 'cxx'
is for badly designed filesystems. 'cc' is the C compiler, not the C++
compiler. 'C' is indistinguishable from 'c' on Mac OS X (HFS+) and
Windows and other 'user friendly' OSes.
'.h' for C and C++ headers. cpp thinks they're the same.
C++ class files and their headers go into the same directory.
One class per header.
Directory structure reflecting namespace:
~ // to get Siphonophora::ComponentKit::Core::Object
~ #include <Siphonophora/ComponentKit/Core/Object.h>
'I' before interface names, unless an adjective:
~ class ITaskManager;
~ class Copyable;
Object classes have nouns for names:
~ class Toy;
~ class Goo;
~ class BlueGoo;
Functions have verbs for names:
~ size_t getSize();
~ void rebalanceTree();
~ template <typename T> T* allocate();
British spelling:
~ ColourPicker colourPicker;
Metric units (preferred, but provide imperial for locale compatibility):
~ double getLengthInCM();
~ double getLengthInInches();
~ length getLength() { return *new Length(this->getLengthInCM(),
Length::cm); }
Always use new-style casts:
~ static_cast<int *>malloc(sizeof(int[128]));
~ const_cast<char *>argv[0]; // Avoid!
~ dynamic_cast<Object>anUnknownObject; // Surround with try catch!
~ reinterpret_cast<unsigned int>aFloat; // Avoid! But a good way to
access the representation of an object in memory.
No publicly accessible variables. Use set/get instead. (Yes, I know it
is slower, but - you can inline it, and the object is notified if
someone changes the variable. Also more flexible about storage of the
variable.)
Those are my eccentricities/coding style. Feel free to argue against -
but be sure to rationalise. We're aiming for code readability, not
file size or character count or anything concrete like that.
Followups to zynot-dev.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQE/5HLqv+6a/MPcjnERAorTAJ97CA3pxhErwdFnLOaBVJ6ftygmUACgjmi5
1xUqswDs3nrk2d2H9TpsUpA=
=92jA
-----END PGP SIGNATURE-----