Read Effective C++ 3rd Edition (More Effective C++ is redundant as it's older than the 3rd edition, which compiled the earlier edition of Effective C++ and More Effective C++) and Effective STL. You'll recognize some of Scott Meyer's tips in the list below, and it will help you write better code.
1) Make Get functions (functions that just return a variable) const, unless it's returning a pointer or reference to a class that needs to be modified. Also use const correctness when passing variables.
2) Name variables so that they tell something about the variable.
Don't use single letter variables. Even if it's x y and z for coordinates, use the prefix to indicate what type it is.
Try to avoid generic variable names; instead of ulIndex, use ulShipIndex when iterating through a list of ships.
Class names should have a C in front of them unless they're functor, e.g. CBasicGameObject
Basic types should have a prefix before the variable name:
- b for BOOL,
- n for INT,
- l for LONG,
- ul for ULONG,
- f for FLOAT,
- d for DOUBLE,
- sz for null terminated strings,
- str for STL strings,
- c for CHAR (or TCHAR),
- by for BYTE (unsigned char)
Class member variables should have m_ as a prefix, e.g. BOOL m_bInitialized;
Pointers should have a p in the name, e.g. CMapData * m_pMapData;
References can have an r in the name, e.g. CMapData & rMapData;
Global variables should have g_ as a prefix, e.g. CResourceManager * g_pResourceManager;
3) Use the typedefs for the basic types; if we have to port our code to another platform, it will be easier to add in a header with the #defines. Try to avoid using ints as the size of ints can vary based on the OS, use LONGs instead. Use BOOL instead of bool when possible.
4) Game objects, data classes, and graphic resources should be ref counted. So derive them from CCoreRefCount.
5) STL algorithms make your life easier and can be faster than doing the same work manually. It's faster to call std::for_each on a vector and pass it a functor than to loop through the vector yourself. If you do need to loop through a vector yourself, use iterators instead of accessing the elements with the [] operator, particularly if you're going to delete items.
6) #include "Kumquat3D.h" in every header file.
Try to avoid using #include for other files in your header file. Use forward declarations if possible in the .h, then use #include in the .cpp. It helps with compile times.
7) Check for existing code before you re-invent the wheel, and ask about code you're not familiar with before changing it.
8) Use Skype + IRC. If you don't need an immediate answer to a question, this is less disruptive. It takes at least 15 minutes to get back in the zone once you get out of it. Also, you can seach chat logs for conversations that happened over IM and you can't for verbal conversations.
9) Get a Google e-mail for Google docs, and a Windows Live ID for Mesh.
10) When designing your code, think about if this is code that may be used again. If so, it may belong in Kumquat3D rather than the game project, or write a base class in Kumquat3D and inherit it in the game project so that you can use app specific code.
11) Write detailed change log entries. A text file to be used for the change log is saved with each project.
12) Commit the entire module at once so that there's less chance of code being left out, and so that people who are trying to update while you're comitting your changes won't get partial changes and have to update again when you're done.
13) Don't hard-code strings, use the string file for screens and data files for strings. Also try to avoid hardcoding filenames.
14) Use TCHAR types and their functions, and use _T() for literal strings. Not all of our code uses TCHARs, but we're converting it as we go.
15) Write wrapper functions instead of accessing screen code directly from game code, if it's absolutely necessary that the code be done in the screen code rather than game code.
16) Use this-> when calling member functions.
17) It's often useful to create typedefs for container classes, so that if you change from using a vector to a deque, you don't have to search and replace in your code, and even if you don't, it makes the code more readable.
e.g. typedef std::vector<CBasicGameObject*> BasicGameObjectArray;
18) Try to remember to get someone to update to grab your changes after you've commited them so that you can make sure that you've checked everything in and that everything works on someone else's computer. Or check it out yourself on your testbox and make sure that it compiles.
19) Function names should indicate what the function does. Get means that it's returning a value; if you're calculating the variable, use Calculate or Convert or something of that sort in the title. If you're doing more than one thing in the function, consider whether you should be breaking it up into smaller functions, particularly if you find yourself copying and pasting code in the same function. Breaking the functions into smaller functions may also help you make the task more efficient.