96
Chapter 6 P olymorphism The is one of the most p o w erful mec hanisms pro vided b y the ob ject- Define p olymorphic variable A orien ted paradigm. A p olymorphic v ariable, y ou will recall, is a v ariable for whic h the static static typ e is asso- t yp e, the t yp e asso ciated with a declaration, ma y di�er from the dynamic t yp e, the t yp e ciate d with a asso ciated with the v alue curren tly b eing held b y the v ariable. de clar ation, a In Ja v a a p olymorphic v ariable can b e declared as either a class t yp e or an in terface t yp e. dynamic typ e If a v ariable is declared as a class t yp e, the v alue held b y the v ariable m ust b e either deriv ed is asso ciate d from the declared class or from a class that inherits from the declared class. If a v ariable with a value is declared using an in terface t yp e, the v alue held b y the v ariable m ust b e deriv ed from a class that implemen ts the giv en in terface. The C language do es not include the concept of ++ in terfaces, and so the idea of a p olymorphic v ariable is only p ossible using class inheritance. There are man y other subtle and not-so-subtle di�erences b et w een p olymorphism in C ++ and p olymorphism in Ja v a, as w e will explain in this c hapter. T o discuss p olymorphism w e need a class hierarc h y . An in tuitiv e hierarc h y is pro vided b y a p ortion of the animal kingdom, whic h w e can represen t as follo ws: Animal � @ � @ Bird Mammal � @ � @ Dog Cat Figure 6.1 pro vides an realization of this class hierarc h y in Ja v a, while Figure 6.2 giv es the corresp onding C co de. W e will use these classes in v arious discussions throughout ++ this c hapter. 97
98 CHAPTER 6. POL YMORPHISM abstract class Animal f abstract public void speak(); g class Bird extends Animal f public void speak() f System.out.printl n( "t wit te r") ; g g class Mammal extends Animal f public void speak() f System.out.printl n( "c an� t speak"); g f g public void bark() System.out.prin tln (" ca n�t bark"); g f class Cat extends Mammal f g public void speak() System.out.printl n( "m eow ") ; f g public void purr() System.out.prin tln (" pu rrr rr "); g f class Dog extends Mammal f g public void speak() System.out.printl n( "w ouf ") ; f g public void bark() System.out.prin tln (" wo uf" ); g Figure 6.1: Animal Kingdom Class Hierarc h y in Ja v a
99 class Animal f public: virtual void speak() = 0; g ; class Bird : public Animal f public: virtual void speak() f printf("twitter" ); g g ; class Mammal : public Animal f public: virtual void speak() f printf("can�t speak"); g f g void bark() printf("can�t bark"); g ; f class Cat : public Mammal public: f g void speak() printf("meow"); f g virtual void purr() printf("purrrrr") ; g ; f class Dog : public Mammal public: virtual void speak() f printf("wouf"); g void bark() f printf("wouf"); g g ; Figure 6.2: Animal Kingdom Class Hierarc h y in C++
100 CHAPTER 6. POL YMORPHISM 6.1 Virtual and Non-virtual Ov erriding Ov erriding o ccurs when a metho d in a paren t class is replaced in a c hild class b y a metho d Define ha ving the exact same t yp e signature. In Ja v a o v erriding is the norm, the exp ected result. In A typ e sig- C , on the other hand, whether o v erriding o ccurs or not is con trolled b y the programmer, ++ natur e is the using the k eyw ord virtual . typ e descrip- The issue in o v erriding is ho w a metho d, that is, the actual co de to b e executed, is tions for e ach b ound to a message. If the virtual k eyw ord is omitted, then the binding is determined b y ar gu- the static typ e of a v ariable, that is, b y the v ariables declared t yp e. This is illustrated b y ment and the the follo wing: typ e descrip- tion of the r e- Dog � d = new Dog(); turn typ e Mammal � m = d; d->bark(); // w ouf can't bark m->bark(); // Because d is declared as a Dog the metho d selected will b e that of the Dog class. Because m is declared only as a Mammal , ev en though it holds exactly the same v alue as do es d , the metho d executed will b e that pro vided b y the class Mammal . Note If, on the other hand, a metho d is declared as virtual , as is the sp eak metho d in Figure 6.2, Vir- tual over- then the metho d in v ok ed ma y , under the righ t circumstances, b e determined b y the dynamic riding c orr e- (that is, run time) v alue held b y the class. This is illustrated b y the follo wing: sp onds to the Java seman- w ouf d->speak(); // tics also w ouf m->speak(); // � Animal a = d; and more w ouf a->speak(); // The metho d sp eak for v ariable d will b e that of class Dog , as migh t b e exp ected. Ho w ev er m will also use the Dog metho d. Ev en a , whic h is an Animal , will use the Dog metho d. Th us, virtual o v erridding corresp onds to the b eha vior of o v erridden functions in Ja v a. Regardless of the t yp e of v alue held b y a v ariable, the v alidit y of a message is determined b y the static, or declared t yp e. This is the same as in Ja v a. Th us while the v ariable d will resp ond to the message ba rk , the v ariable a that w as declared as Animal , ev en though it con tains the exact same v alue, is not allo w ed to p erform this op eration. w ouf d->bark(); // compile error, not allo w ed a->bark(); // Because of the C memory mo del (see Chapter 4) virtual, or p olymorphic, o v erriding ++ will only o ccur when used with a p oin ter or reference, and not with stac k-based v ariables. This is illustrated b y the follo wing:
6.1. VIR TUAL AND NON-VIR TUAL O VERRIDING 101 Mammal mm; � d; mm = mm.speak(); // can't sp eak d->speak(); // although dog will w ouf Note that the v ariable mm is here not declared as a p oin ter, as w ere earlier v ariables, but as a simple stac k-based v alue. The Dog v alue held b y d is assigned to the v ariable mm . During the assignmen t pro cess the v alue loses its dog iden tit y , and b ecomes simply a mammal. Th us the sp eak metho d will b e that of class Mammal , not that of class Dog . The pseudo-v ariable this , the reference to the receiv er within a metho d, is a p oin ter in Note The C , whereas it is an ob ject v alue in Ja v a. Th us, implicit messages sen t to this can ha v e variable this ++ is p olymorphic bindings. a p ointer in If a v ariable is not declared as virtual in a paren t class, it cannot subsequen tly b e made C , a vari- ++ virtual in a c hild class. On the other hand, the k eyw ord is optional in the c hild class; once able in Java declared as virtual b y the paren t, the metho d remains virtual in all c hild class de�nitions. Notice that w e ha v e made use of this fact b y omitting the virtual k eyw ord from the sp eci�- cation of the metho d sp eak in class Cat . Despite this, the metho d still remains virtual. 6.1.1 Impact of Virtual on Size Note When a class description con tains a virtual metho d, an in ternal table is created for the class, called the virtual metho d table. This table is used in the implemen tation of the dynamic When classes c ontain vir- binding of message to metho d required b y the virtual metho d. In order to do this, eac h tual metho ds, instance of a class will con tain an additional hidden p oin ter v alue, whic h references the instanc es wil l virtual metho d table. The programmer can see this e�ect b y adding or remo ving the virtual hold a hidden k eyw ord from a class description, and examining the size of an instance of the class: p ointer to a virtual class sizeTest f metho d table public: int x, y; virtual void test () f x = 3; g g ; sizeTest x; size will b e 8 if not virtual, larger if virtual // println("%d\n", sizeof(x) );
Recommend
More recommend