Could you give a brief explanation as to why you dislike the book, and also what revision you're talking about.
O_o
I'd say the Deitel, as if literature, were poorly paced with gaping "plot holes" and entirely too much "overshadowing".
I'd have to dig around to find revisions, but as for why: the Deitel books I've read are only a few dozen steps away from what is expected of Herbert Schildt.
So, yeah, infinitely better than Herbert Schildt books, but still, the Deitel books, while mostly correct with descriptions actually honoring code examples, get a lot of stuff, notably exceptions and canonical forms of common idioms, wrong. The Deitel books do decent coverage--more than can be said for Herbert Schildt books--of "RAII" and the "copy/swap idiom" for example, but the coverage is opposed to canonical normal forms, and such problems as I have mostly come from poorly ordered, structure, material with breaking references to other material. (You'll repeatedly see early examples with much too much complexity referencing material which will not be explained until chapters later which depends on material from earlier chapters. You'll repeatedly see later examples without enough complexity where the material is simply repeating how two pieces fit together because the earlier examples already have shown how the same two pieces fit together with a reference to coming material.)
That sort of thing may not sound like a great sin, but canonical expectations are actually codified for a reason in C++.
Code:
class SExample
{
// ...
SExample & operator =
(
const SExample & fRHS
)
{
return(SExample(fRHS).replace(*this));
}
// ...
SExample & replace
(
SExample & fRHS
)
{
int mTemp(mData);
mData = fRHS.mData;
fRHS.mData = mTemp;
return(*this);
}
// ...
int mData;
};
I guess there is nothing really wrong with introducing the "copy/swap idiom" with different names and slightly different external functionality. (You can even easily add a non-member, non-friend `swap' using `replace' to do the job.) However, if we wait until we have covered more of the foundation--thus waiting on introducing the "copy/swap idiom" until a perfect place to introduce the canonical form of the concept is available--we may offer an explanation of the rationale and one of many reasons behind the use of "using declarations" at reduced scope in a more complex but infinitely more illustrative example.
Code:
class SExample
{
// ...
SExample
(
const SExample & fOther
):
mData(0)
, mSize(0)
{
if(fOther.mData && fOther.mSize)
{
// We allow the exception to propagate
// preventing us from using a bad pointer.
mData = new int[mSize];
// (Omitted) We use `std::copy' to copy the array of integer values.
}
}
// ...
SExample & operator =
(
SExample fRHS // We require a copy for destructive use as a temporary.
)
{
fRHS.swap(*this); // We can simply move the values of members between
return(*this); // instances because we have a temporary available.
// The temporary will be destroyed which will cleanup
// the resource we had owned.
}
// ...
void swap
(
SExample & fOther
)
{
// Ask the compiler to use "Argument-dependent Name Lookup" to resolve
// which implementation of `swap' to use for each member.
using std::swap;
swap(mData, fOther.mData); // These data members are trivial types so swapping
swap(mSize, fOther.mSize); // is an operation which does not raise exceptions.
}
// ...
int * mData;
int mSize;
};
// ...
// By using the same feature from `SExample::swap', "Argument-dependent Name Lookup",
// we may now provide a swapping operation available to client code for our
// `SExample' class which does not raise exceptions.
void swap
(
SExample & fLHS
, SExample & fRHS
)
{
fLHS.swap(fRHS);
}
Instead of introducing a trivial example early only to show the "copy/swap idiom" at home, we have introduced an example strictly building on material learned from previous examples which shows why the "copy/swap idiom" exists, the normal interface, and the canonical implementation.
Semantically, the example I've offered does a lot more with only a little more code.
Soma