[ Team LiB ] Previous Section Next Section

Gotcha #33: Misunderstanding Pointer-to-Pointer-to-Base Conversion

We face a similar situation with pointers to pointers to derived classes:



D1 d1; 


D1 *d1p = &d1; // OK


B **ppb1 = &d1p; // error, fortunately


D2 *d2p;


B **ppb2 = &d2p; // error, fortunately


*ppb2 = *ppb1; // now d2p points to a D1!


Look familiar? Just as the const-conversion property doesn't hold if one introduces another level of indirection, the same is the case with the is-a property. While a pointer to a derived class is-a pointer to a public base, a pointer to a pointer to a derived class is not a pointer to a pointer to a public base. As with the analogous const example, the situation that results in an error initially looks contrived. However, it's easy to construct a situation that produces an error as a cooperative effort between a bad interface design and an incorrect use of the interface:



void doBs( B *bs[], B *pb ) { 


       for( int i = 0; bs[i]; ++i )


               if( somecondition( bs[i], pb ) )


                      bs[i] = pb; // oops!


}


// . . .


extern D1 *array[];


D2 *aD2 = getMeAD2();


doBs( (B **)array, aD2 ); // another casted death wish . . .


Once again, the developer assumes the compiler is in error and circumvents the type system with a cast. In this case, though, the designer of the function interface has a lot to answer for as well. A safer design would have employed a container that didn't permit spoofing by cast, as an array does.

    [ Team LiB ] Previous Section Next Section