[ Pobierz całość w formacie PDF ]
.If a methoddoes not have the proper type, the ANSI-C compiler will not detect the errorbecause the variable argument list and our casting prevent type checks.Here werely on the programmer to match the selector to the method supplied with it, butthey must be specified as a pair and that should result in a certain amount of plausi-bility. 6.7 Initialization 65___________________________________________________________________________6.7 InitializationNormally we obtain a class description by sending new() to a metaclass description.In the case of Class and Object we would issue the following calls:const void * Object = new(Class,"Object", Object, sizeof(struct Object),ctor, Object_ctor,dtor, Object_dtor,differ, Object_differ,puto, Object_puto,0);const void * Class = new(Class,"Class", Object, sizeof(struct Class),ctor, Class_ctor,dtor, Class_dtor,0);Unfortunately, either call relies on the other already having been completed.There-fore, the implementation of Class and Object in Object.c requires static initializationof the class descriptions.This is the only point where we explicitly initialize a structClass:static const struct Class object [] = {{ { object + 1 },"Object", object, sizeof(struct Object),Object_ctor, Object_dtor, Object_differ, Object_puto},{ { object + 1 },"Class", object, sizeof(struct Class),Class_ctor, Class_dtor, Object_differ, Object_puto}};const void * Object = object;const void * Class = object + 1;An array name is the address of the first array element and can already be used toinitialize components of the elements.We fully parenthesize this initialization incase struct Object is changed later on.6.8 SelectorsThe job of a selector function is unchanged from chapter 2: One argument _self isthe object for dynamic linkage.We verify that it exists and that the requiredmethod exists for the object.Then we call the method and pass all arguments to it;therefore, the method can assume that _self is a proper object for it.Finally, wereturn the result value of the method, if any, as the result of the selector.Every dynamically linked method must have a selector.So far, we have hiddencalls to the constructor and the destructor behind new() and delete(), but we stillneed the function names ctor and dtor for the selector/method pairs passed to theClass constructor.We may later decide to bind new() and delete() dynamically;therefore, it would not be a good idea to use their names in place of ctor and dtor. 66 6 Class Hierarchy  Maintainability___________________________________________________________________________We have introduced a common superclass Object for all our classes and wehave given it some functionality that simplifies implementing selector functions.classOf() inspects an object and returns a non-zero pointer to its class description.This permits the following implementation for delete():void delete (void * _self){if (_self)free(dtor(_self));}void * dtor (void * _self){ const struct Class * class = classOf(_self);assert(class  > dtor);return class  > dtor(_self);}new() must be implemented very carefully but it works similarly:void * new (const void * _class,.){ const struct Class * class = _class;struct Object * object;va_list ap;assert(class && class  > size);object = calloc(1, class  > size);assert(object);object  > class = class;va_start(ap, _class);object = ctor(object, & ap);va_end(ap);return object;}We verify the class description and we make sure that we can create a zero-filledobject.Then we initialize the class description of the object and we are ready to letthe normal selector ctor() find and execute the constructor:void * ctor (void * _self, va_list * app){ const struct Class * class = classOf(_self);assert(class  > ctor);return class  > ctor(_self, app);}There is perhaps a bit too much checking going on, but we have a uniform androbust interface.6.9 Superclass SelectorsBefore a subclass constructor performs its own initialization, it is required to call thesuperclass constructor.Similarly, a subclass destructor must call its superclassdestructor after it has completed its own resource reclamation.When we areimplementing selector functions, we should also supply selectors for the superclasscalls: 6.9 Superclass Selectors 67___________________________________________________________________________void * super_ctor (const void * _class,void * _self, va_list * app){ const struct Class * superclass = super(_class);assert(_self && superclass  > ctor);return superclass  > ctor(_self, app);}void * super_dtor (const void * _class, void * _self){ const struct Class * superclass = super(_class);assert(_self && superclass  > dtor);return superclass  > dtor(_self);}These selectors should only be called by a subclass implementation; therefore, weinclude their declarations into the representation file and not into the interface file.To be on the safe side, we supply superclass selectors for all dynamically linkedmethods, i.e., every selector has a corresponding superclass selector.This way,every dynamically linked method has a simple way to call its superclass method.Actually, there is a subtle trap luring.Consider how a method of an arbitraryclass X would call its superclass method.This is the correct way:static void * X_method (void * _self, va_list * app){ void * p = super_method(X, _self, app);.Looking at the superclass selectors shown above we see that super_method() inthis case callssuper(X)  > method(_self, app);i.e., the method in the superclass of the class X for which we just definedX_method().The same method is still reached even if some subclass Y inheritedX_method() because the implementation is independent of any future inheritance.The following code for X_method() may look more plausible, but it will breakonce the method is inherited:static void * X_method (void * _self, va_list * app){ void * p = /* WRONG */super_method(classOf(_self), _self, app);.The superclass selector definition now producessuper(classOf(_self))  > method(_self, app);If _self is in class X, we reach the same method as before [ Pobierz całość w formacie PDF ]

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • wpserwis.htw.pl