Friday, April 25, 2003

Updated EC++ Errata; 11/02 CUJ Article now Available

Two things:
- Effective C++ Errata Updated
- My November 2002 CUJ Article is now Online

I just updated the errata list for Effective C++. As always, it's at A detailed
list of changes (in the usual pseudo-HTML I use internally) is listed
below. In conjunction with the recent updates I made to the errata pages
for ESTL and MEC++, I'm pleased to report that all the problems I know
about in my books are now listed online.

Also, you can now find a PDF copy of my November 2002 CUJ article, "Class
Template, Member Template -- or Both?" at



[New EC++ Errata Entries]

-------- --- ----- ------------------------------------------------ --------
10/12/02 bj 12 Clarify whether the "ISO/ANSI sanctified version
of C" I refer to in the book is now C99, not C89.

4/10/03 wk 77 The final bullet point on the page is misleading.
C++ imposes constraints on how copy constructors
behave, so rather than writing that a copy
constructor defines what it means to pass by
value, I should say that it defines how an
object is passed by value.

10/20/02 kk 125 In final sentence of 2nd-to-last paragraph,
clarify that callers must use the array form of

9/26/02 mh 127 It would be better if someFamousAuthor returned
a const String instead of just a String. This
would be consistent with the advice of Item 21.

10/12/02 bj 135 In first para, note that the "C philosophy that
variables should be defined at the beginning of
a block" is for C prior to C99.

! 10/12/02 bj Item 41 The first design problem includes the ability to
create "stacks of stacks of strings," but the
given solution has a private copy constructor,
making it impossible to create a Stack of Stacks.

Interesting Comments:

-------- --- ----- -----------------------------------------------------------
2/17/03 dyx Items "Our programming guidelines now recommend implementing
16-17 assignment operators like this:

T const& T::operator=( T other )
swap( other ); // non-throwing operation
return *this;

My reply:

This is fine (except for the const return type :-}), as
long as you make clear that this approach may be
needlessly expensive. For example, if all your data
members are of built in types, their assignments can't
throw, so doing swaps instead of assignments just burns
cycles needlessly. For large objects, you're talking
about duplicating an object's contents on the heap in
order to be able to perform the non-throwing swap.
There's nothing wrong with that, but my experience has
been that people advocating this approach to implementing
operator= often overlook the cost that it incurs. It's
exception safe, but it's often not cheap.

12/30/02 ma Item 19 It's true that virtual functions must be members, but one
can get virtual-acting behavior by having a non-virtual
function (possibly a non-member) call a virtual function.
This can be especially useful for functions like operator<<,
which must be non-members but can be made to act virtual by
internally calling a virtual function, e.g., one named
"print" or "write".

2/17/03 dys Item 19 Regarding the last bullet on page 88, dys writes:

The same rule should be used for other operators that
require a different class as a left-hand operand. For
example, CORBA uses "Any <<= Type", and for all classes
besides Any, operator<<=(T) is a non-member. I propose
the following change to your algorithm. Instead of

else if (f is operator>> or operator<<)


else if (f is an operator and needs another class as
its left-hand operand)

6/15/02 sdm Item 33 Randy Meyers (no relation) has a nice article on inlining
in C99, including an explanation of how the C99 rules differ
from those in C++, in the July 2002 issue of the
Users Journal

10/13/02 ya Item 36 ya writes: "Nonvirtual functions may call other functions
which are virtual. In that case, derived classes are indeed
presented with mandadory implementation, but only in the
highest, close-to-the-surface level. By overriding virtual
functions, the overall behavior of the nonvirtual function
can change in derived classes. Such usage of nonvirtuals is
very useful and is the basis for the 'template method'
design pattern."
This is true, but it's important to note that the
externally observable behavior of any function is defined by
its specification (i.e., it's interface), not by its
implementation. A nonvirtual implemented using template
method may behave differently for different derived classes,
but its behavior is still bounded by its specification.
Callers don't care whether the function is virtual or
nonvirtual. All they care about is that the function they
call exhibits the behavior its specification promises.
For implementers of derived classes, it's a different
story. They care very much about whether a base class
function is virtual or nonvirtual, because that affects what
they are allowed to vary. In Item 36, my remarks are
focused on the relationship between authors of base and
derived classes, not on the relationship between authors of
a class and clients of that class.

No comments: