Question about C ++ programming language

Chapter 24.3.4 of the book "C ++ Programming Language" says that

class Cfield : public Field{ /*...*/ } 

This expresses the idea that a Cfield indeed a kind of field, allows you to use a Cfield function that uses a member of the Cfield field, and - most importantly - allows Cfield redefine the field of virtual functions. The trap is this: converting Cfield* to Field* implied in the Cfield all attempts to control access to Field :

 void g(Cfield* p) { *p = "asdf"; // access to Field controlled by Cfield 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 a bold suggestion. How did Cfield cancel Field access control attempts?

Actually, the last line of code:

 *q = "asdf"; 

will call Field::operator=("asdf") since Cfield canceled an attempt to control access to the Field ?

+4
source share
3 answers

Here is a concrete example:

 struct Field { Field(char const* s): string(s) {} char const* string; }; struct CField: Field { CField(char const* s): Field(s), length(s ? ::strlen(s) : 0) {} std::size_t length; }; 

This is a very simple string type that does not allow you to modify the string to which it refers. CField adds the Field class by caching the string length.

Now, in action:

 void foo(CField& cf) { // 0 cf = "foo"; // 1 Field& f = cf; // 2 f = "foobar"; // 3 } 

What's happening?

  • line 0: unknown state
  • line 1: calling CField& CField::operator=(CField const&) , which creates a temporary CField (using the constructor), cf.string is "foo" and cf.length is 3
  • line 2: the same object, accessed through Field directly
  • line 3: calling Field& Field::operator=(Field const&) , which creates a temporary Field (using the constructor), cf.string is "foobar" and cf.length is 3 (no change)

As you can see, the invariant that length caches the length of the string is corrupted due to insecure access to the string via Field& .

+1
source

CField It is assumed that instances must provide controlled (that is, verified in some way CField::operator=() ) access to the data of the Field base class. But if you implicitly drop CField * in Field * , and then play it out, this control is gone because you select Field::operator=() .

I agree that this is not the most clear of the BS letters, and it seems to me that this is not a problem, you can always get "uncontrolled access" to anything if you put your mind into it.

+4
source

I assume this is related to the problem that the Cfield assignment Cfield can create special things that are necessary to match the state of an object. Using the superclass assignment operator, invariants can be broken.

+2
source

All Articles