The 50 Ways:
Scott Meyers' More Effective C++
- Prefer
const
and inline
to #define
.
- Prefer
<iostream>
to <stdio.h>
.
- Prefer
new
and delete
to malloc
and free
.
//Prefer C++-style comments.
- Use the same form in corresponding uses of
new
and delete
.
- Use
delete
on pointer members in destructors.
- Be prepared for out-of-memory conditions
(
set_new_handler
).
- Adhere to convention when writing
operator new
and operator delete
.
- Avoid hiding the "normal" form of
new
.
- [Author]
operator delete
if you [author]
operator new
.
- Declare a copy constructor and an assignment
operator for classes with dynamically
allocated memory.
- Prefer initialization to assignment in
constructors.
- List members in an initialization list
in the order in which they are declared.
- Make sure that base classes have
virtual
destructors.
- Have
operator=
return
a reference
to *this
(known familiarly as the this-pointer).
- Assign to all data members
in
operator=
.
- Check for assignment to self in
operator=
.
- Strive for class interfaces that
are complete and minimal.
- Differentiate among member functions,
non-member functions
and
friend
functions.
- Avoid data members in the public
interface.
- Use
const
whenver possible.
- Prefer pass-by-reference to pass-by-value.
- Don't try to
return
a reference
when you must return
an object.
- Choose carefully between function
overloading and parameter
defaulting.
- Avoid overloading on a pointer and a numerical
type.
- Guard against potential ambiguity.
Explicit
ly disallow the use of implicit
ly-generated
member functions [that] you don't want.
- Partition the global
namespace
.
- Avoid
return
ing "handles"
to internal data.
- Avoid member functions that
return non-
const
pointers
or references to members less accessible
than themselves.
- Never
return
a reference to a local
object or to a dereferenced
pointer [that is] initialized by new
within the function.
- Postpone variable definition as
long as possible.
- Use
inlin
ing judiciously.
- Minimize compilation dependencies between files.
- Make sure [that] public inheritance
models "is-a."
- Differentiate between inheritance of interface
and inheritance of implementation.
- Never redefine an inherited
non-
virtual
function.
- Never redefine an inherited default
parameter value.
- Avoid casts down the inheritance
hierarchy.
- Model "has-a" or "is-implemented-in-terms-of"
through layering.
- Differentiate between inheritance and
template
s.
- Use
private
inheritance
judiciously.
- Use multiple inheritance
judiciously.
- Say what you mean; understand what you're saying:
- Know what functions C++ silently writes
and calls.
- Prefer compile-time [errors] and
link-time errors to runtime
errors.
- Ensure that non-local
static
objects are initialized before they are used.
- Pay attention to compiler warnings.
- Familiarize yourself with the Standard Library.
- 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:
- How should objects be created and
destroyed?
- How does initialization differ from object
assignment?
- What does it mean to pass objects of the
new type by value?
- What are the constraints on legal values
for the new type?
- Does the new type fit into an inheritance
graph?
- What kind of type conversions are allowed?
- What operators and functions make sense
for the new type
- What functions and operators should be
explicitly disallowed?
- Who should have access to the members of
the new type?
- How general is the new type?
-- Ernie