In Chapter 24.3.4 of the book The C++ Programming Language it said that
class Cfield : public Field{ /*...*/ }This expresses the notion that a
Cfieldreally is a kind of Field,
allows notational convenience when
writing aCfieldfunction that uses a
member of the Field part of the
Cfield, and – most importantly –
allows aCfieldto override Field
virtual functions. The snag is that
theCfield*toField*conversion
implied in the declaration ofCfield
defeats all attempts to control access
to theField:void g(Cfield* p) { *p = "asdf"; // access to Field controlled by Cfield's assignment operator: // p->Cfield::operator=("asdf") Field* q = p; // implicit Cfield* to Field* conversion *q = "asdf" // OOPS! no control }
What I DO NOT understand here, is the bolded sentence. How did Cfield defeat the attempt to control access to Field?
Actually, the last line of the code:
*q = "asdf";
will call Field::operator=("asdf"), so how did Cfield defeat the attempt to control access to Field?
Let’s give a concrete example:
This is a very basic kind of string, that does not allow modification of the string it refers too.
CFieldaugments theFieldclass by caching the length of the string.Now, in action:
What happens ?
CField& CField::operator=(CField const&), which creates a temporaryCField(using the constructor),cf.stringis"foo"andcf.lengthis3FielddirectlyField& Field::operator=(Field const&), which creates a temporaryField(using the constructor),cf.stringis"foobar"andcf.lengthis3(unchanged)As you can note, the invariant that
lengthcaches the length of thestringis broken because of the unprotected access tostringviaField&.