The 50 Ways:

Scott Meyers' More Effective C++

  1. Prefer const and inline to #define.
  2. Prefer <iostream> to <stdio.h>.
  3. Prefer new and delete to malloc and free.
  4. //Prefer C++-style comments.
  5. Use the same form in corresponding uses of new and delete.
  6. Use delete on pointer members in destructors.
  7. Be prepared for out-of-memory conditions (set_new_handler).
  8. Adhere to convention when writing operator new and operator delete.
  9. Avoid hiding the "normal" form of new.
  10. [Author] operator delete if you [author] operator new.
  11. Declare a copy constructor and an assignment operator for classes with dynamically allocated memory.
  12. Prefer initialization to assignment in constructors.
  13. List members in an initialization list in the order in which they are declared.
  14. Make sure that base classes have virtual destructors.
  15. Have operator= return a reference to *this (known familiarly as the this-pointer).
  16. Assign to all data members in operator=.
  17. Check for assignment to self in operator=.
  18. Strive for class interfaces that are complete and minimal.
  19. Differentiate among member functions, non-member functions and friend functions.
  20. Avoid data members in the public interface.
  21. Use const whenver possible.
  22. Prefer pass-by-reference to pass-by-value.
  23. Don't try to return a reference when you must return an object.
  24. Choose carefully between function overloading and parameter defaulting.
  25. Avoid overloading on a pointer and a numerical type.
  26. Guard against potential ambiguity.
  27. Explicitly disallow the use of implicitly-generated member functions [that] you don't want.
  28. Partition the global namespace.
  29. Avoid returning "handles" to internal data.
  30. Avoid member functions that return non-const pointers or references to members less accessible than themselves.
  31. Never return a reference to a local object or to a dereferenced pointer [that is] initialized by new within the function.
  32. Postpone variable definition as long as possible.
  33. Use inlining judiciously.
  34. Minimize compilation dependencies between files.
  35. Make sure [that] public inheritance models "is-a."
  36. Differentiate between inheritance of interface and inheritance of implementation.
  37. Never redefine an inherited non-virtual function.
  38. Never redefine an inherited default parameter value.
  39. Avoid casts down the inheritance hierarchy.
  40. Model "has-a" or "is-implemented-in-terms-of" through layering.
  41. Differentiate between inheritance and templates.
  42. Use private inheritance judiciously.
  43. Use multiple inheritance judiciously.
  44. Say what you mean; understand what you're saying:
  45. A common base means common traits.
  46. Public inheritance means "is-a."
  47. Private inheritance means "is-implemented-in-terms-of."
  48. Layering means "has-a" or "is-implemented-in-terms-of."
  49. A pure virtual function means that only the function's interface is inherited.
  50. A simple virtual function means that the function's interface PLUS a default implementation [are] inherited.
  51. Know what functions C++ silently writes and calls.
  52. Prefer compile-time [errors] and link-time errors to runtime errors.
  53. Ensure that non-local static objects are initialized before they are used.
  54. Pay attention to compiler warnings.
  55. Familiarize yourself with the Standard Library.
  56. Improve your understanding of C++.

My apologies to the author, but I have added to or changed some of the language above where I thought it might add to the clarity in the absence of his lucid discussion of the points above. The emphasis is also mine: I discriminated between jargon, specialized language and code/keywords where Scott Meyers may not have done so. I find that as programmers we often assume that "laypersons" or non-technical members of our community understand that we refer to specialized terminology without indicating this special meaning to our audience. I added this extra layer of marking to assist those who may be otherwise confused by a lack of intimacy with programmer dialects.

An addendum: Perhaps as important as the points that the author makes by his specific recommendations above are his general recommendations in the form of "questions to ask oneself about creation/authoring an object." These questions follow below:

  1. How should objects be created and destroyed?
  2. How does initialization differ from object assignment?
  3. What does it mean to pass objects of the new type by value?
  4. What are the constraints on legal values for the new type?
  5. Does the new type fit into an inheritance graph?
  6. What kind of type conversions are allowed?
  7. What operators and functions make sense for the new type
  8. What functions and operators should be explicitly disallowed?
  9. Who should have access to the members of the new type?
  10. How general is the new type?

-- Ernie