96 Chapter 6 P olymorphism The is one of the most p o w - - PDF document

96 chapter 6 p olymorphism the is one of the most p o w
SMART_READER_LITE
LIVE PREVIEW

96 Chapter 6 P olymorphism The is one of the most p o w - - PDF document

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


slide-1
SLIDE 1 96
slide-2
SLIDE 2 Chapter 6 P
  • lymorphism
The p
  • lymorphic
variable is
  • ne
  • f
the most p
  • w
erful mec hanisms pro vided b y the
  • b
ject- Define A static typ e is asso- ciate d with a de clar ation, a dynamic typ e is asso ciate d with a value
  • rien
ted paradigm. A p
  • lymorphic
v ariable, y
  • u
will recall, is a v ariable for whic h the static t yp e, the t yp e asso ciated with a declaration, ma y dier from the dynamic t yp e, the t yp e asso ciated with the v alue curren tly b eing held b y the v ariable. In Ja v a a p
  • lymorphic
v ariable can b e declared as either a class t yp e
  • r
an in terface t yp 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 from the declared class
  • r
from a class that inherits from the declared class. If a v ariable 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
  • f
in terfaces, and so the idea
  • f
a p
  • lymorphic
v ariable is
  • nly
p
  • ssible
using class inheritance. There are man y
  • ther
subtle and not-so-subtle dierences b et w een p
  • lymorphism
in C ++ and p
  • lymorphism
in Ja v a, as w e will explain in this c hapter. T
  • discuss
p
  • lymorphism
w e need a class hierarc h y . An in tuitiv e hierarc h y is pro vided b y a p
  • rtion
  • f
the animal kingdom, whic h w e can represen t as follo ws: Bird Animal Cat Mammal Dog
  • @
@ @ @ Figure 6.1 pro vides an realization
  • f
this class hierarc h y in Ja v a, while Figure 6.2 giv es the corresp
  • nding
C ++ co de. W e will use these classes in v arious discussions throughout this c hapter. 97
slide-3
SLIDE 3 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 public void bark() f System.out.prin tln (" ca nt bark"); g g class Cat extends Mammal f public void speak() f System.out.printl n( "m eow ") ; g public void purr() f System.out.prin tln (" pu rrr rr "); g g class Dog extends Mammal f public void speak() f System.out.printl n( "w
  • uf
") ; g public void bark() f System.out.prin tln (" wo uf" ); g g Figure 6.1: Animal Kingdom Class Hierarc h y in Ja v a
slide-4
SLIDE 4 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("cant speak"); g void bark() f printf("cant bark"); g g; class Cat : public Mammal f public: void speak() f printf("meow"); g virtual void purr() f printf("purrrrr") ; g g; class Dog : public Mammal f 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++
slide-5
SLIDE 5 100 CHAPTER 6. POL YMORPHISM 6.1 Virtual and Non-virtual Ov erriding Ov erriding
  • ccurs
when a metho d in a paren t class is replaced in a c hild class b y a metho d ha ving the exact same t yp e signature. In Ja v a
  • v
erriding is the norm, the exp ected result. In Define A typ e sig- natur e is the typ e descrip- tions for e ach ar gu- ment and the typ e descrip- tion
  • f
the r e- turn typ e C ++ ,
  • n
the
  • ther
hand, whether
  • v
erriding
  • ccurs
  • r
not is con trolled b y the programmer, using the k eyw
  • rd
virtual. The issue in
  • v
erriding is ho w a metho d, that is, the actual co de to b e executed, is b
  • und
to a message. If the virtual k eyw
  • rd
is
  • mitted,
then the binding is determined b y the static typ e
  • f
a v ariable, that is, b y the v ariables declared t yp e. This is illustrated b y the follo wing: Dog
  • d
= new Dog(); Mammal
  • m
= d; d->bark(); // w
  • uf
m->bark(); // can't bark Because d is declared as a Dog the metho d selected will b e that
  • f
the Dog class. Because m is declared
  • nly
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. If,
  • n
the
  • ther
hand, a metho d is declared as virtual, as is the sp eak metho d in Figure 6.2, Note Vir- tual
  • ver-
riding c
  • rr
e- sp
  • nds
to the Java seman- tics then the metho d in v
  • k
ed ma y , under the righ t circumstances, b e determined b y the dynamic (that is, run time) v alue held b y the class. This is illustrated b y the follo wing: d->speak(); // w
  • uf
m->speak(); // also w
  • uf
Animal
  • a
= d; a->speak(); // and more w
  • uf
The metho d sp eak for v ariable d will b e that
  • f
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
  • v
erridding corresp
  • nds
to the b eha vior
  • f
  • v
erridden functions in Ja v a. Regardless
  • f
the t yp e
  • f
v alue held b y a v ariable, the v alidit y
  • f
a message is determined b y the static,
  • r
declared t yp e. This is the same as in Ja v a. Th us while the v ariable d will resp
  • nd
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
  • p
eration. d->bark(); // w
  • uf
a->bark(); // compile error, not allo w ed Because
  • f
the C ++ memory mo del (see Chapter 4) virtual,
  • r
p
  • lymorphic,
  • v
erriding will
  • nly
  • ccur
when used with a p
  • in
ter
  • r
reference, and not with stac k-based v ariables. This is illustrated b y the follo wing:
slide-6
SLIDE 6 6.1. VIR TUAL AND NON-VIR TUAL O VERRIDING 101 Mammal mm; mm = d; mm.speak(); // can't sp eak d->speak(); // although dog will w
  • uf
Note that the v ariable mm is here not declared as a p
  • in
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
  • f
class Mammal, not that
  • f
class Dog. The pseudo-v ariable this, the reference to the receiv er within a metho d, is a p
  • in
ter in Note The variable this is a p
  • inter
in C ++ , a vari- able in Java C ++ , whereas it is an
  • b
ject v alue in Ja v a. Th us, implicit messages sen t to this can ha v e p
  • lymorphic
bindings. If a v ariable is not declared as virtual in a paren t class, it cannot subsequen tly b e made virtual in a c hild class. On the
  • ther
hand, the k eyw
  • rd
is
  • ptional
in the c hild class;
  • nce
declared as virtual b y the paren t, the metho d remains virtual in all c hild class denitions. Notice that w e ha v e made use
  • f
this fact b y
  • mitting
the virtual k eyw
  • rd
from the sp eci- cation
  • f
the metho d sp eak in class Cat. Despite this, the metho d still remains virtual. 6.1.1 Impact
  • f
Virtual
  • n
Size When a class description con tains a virtual metho d, an in ternal table is created for the class, Note When classes c
  • ntain
vir- tual metho ds, instanc es wil l hold a hidden p
  • inter
to a virtual metho d table called the virtual metho d table. This table is used in the implemen tation
  • f
the dynamic binding
  • f
message to metho d required b y the virtual metho d. In
  • rder
to do this, eac h instance
  • f
a class will con tain an additional hidden p
  • in
ter v alue, whic h references the virtual metho d table. The programmer can see this eect b y adding
  • r
remo ving the virtual k eyw
  • rd
from a class description, and examining the size
  • f
an instance
  • f
the class: class sizeTest f 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) );
slide-7
SLIDE 7 102 CHAPTER 6. POL YMORPHISM 6.1.2 Obtaining T yp e Information from a dynamic v alue In Ja v a all
  • b
jects recognize the metho d getClass(), and in resp
  • nse
will yield a Class
  • b
ject that describ es the dynamic t yp e
  • f
the v alue. Using the Class v alue
  • ne
can
  • btain
v arious bits
  • f
information ab
  • ut
the v alue, for example a string that describ es the dynamic t yp e: Animal a = new Dog(); // follo wing will prin t class Dog System.out.printl n( "cl as s is " + a.getClass().ge tNa me ()) ; The equiv alen t feature in C ++ is a function named t yp eid. The t yp eid function returns a W arning The t yp eid fe atur e is a r e c ent addi- tion to C ++ v alue
  • f
t yp e t yp einfo, describ ed b y the include le
  • f
the same name. The string represen- tation
  • f
the name
  • f
the class if yielded b y the metho d name: Animal
  • a
= new Dog(); // will prin t the class Dog println("class is %s\n", typeid(a).name( )) ; Notice it is necessary to dereference the v ariable a, since the t yp eid m ust act
  • n
the v alue a p
  • in
ts to, not the p
  • in
ter v alue itself. Being a relativ ely recen t addition to C ++ , the t yp eid facilit y is
  • ne
  • f
the few places in the standard library that will generate an exception
  • n
error. Should the p
  • in
ter v alue in the ab
  • v
e expression b e n ull, a bad t yp eid exception will b e thro wn. 6.2 Abstract Classes An abstr act class is a class used
  • nly
as a paren t class for inheritance,
  • ne
that cannot b e used to create instances directly . The Ja v a language includes an explicit k eyw
  • rd
abstract to indicate this situation. The C ++ language do es not use this k eyw
  • rd.
Instead, an abstract class is simply a class that includes a pur e virtual metho d. A pure virtual metho d is a Define A pur e virtual metho d must b e
  • verridden
in sub classes metho d that is declared as virtual but whic h do es not include a metho d b
  • dy
. Instead, the metho d is \assigned" the n ull v alue. An example
  • ccurs
in Figure 6.2: class Animal f public: virtual void speak() = 0; g; As with abstract classes in Ja v a, it is not p
  • ssible
to create an instance
  • f
a class that con tains a pure virtual mem b er. An attempt to do so will pro duce a compile time error message.
slide-8
SLIDE 8 6.3. DO WNCASTING (REVERSE POL YMORPHISM) 103 As w e noted at the b eginning
  • f
this c hapter, the C ++ language do es not pro vide the Note A n interfac e c an b e simulate d by pur e vir- tual metho ds interface facilit y . Sometimes classes that consist en tirely
  • f
pure virtual metho ds are used in the same manner as in terfaces: class KeyPressHandler f // sp ecication for k ey press ev en t handler public: virtual void keyDown (char c) = 0; g; class MouseDownHandler f // sp ecication for mouse do wn ev en t handler public: virtual void mouseDown (int x, int y) = 0; virtual void mouseUp (int x, int y) = 0; g; Since C ++ supp
  • rts
m ultiple inheritance (see Section 12.8), a class can implemen t sev eral
  • f
suc h in terfaces: class EventHandler : public KeyPressHandler, public MouseDownHandler f public: void keyDown (char c) f ... g void mouseDown (int x, int y) f ... g void mouseUp (int x, int y)( f ... g g; In Ja v a the k eyw
  • rd
nal is in some w a ys the
  • pp
  • site
  • f
abstract, serving to indicate metho ds
  • r
classes that cannot b e
  • v
erwritten. There is no equiv alen t feature in C ++ , although as w e noted in the previous c hapter in some cases declaring the constructor for a class as p rotected can ha v e a similar eect. 6.3 Do wncasting (Rev erse P
  • lymorphism)
A p
  • lymorphic
v ariable can ha v e a dynamic t yp e that is a sub class
  • f
its static,
  • r
declared Note Downc asting r everses the assignment to a p
  • lymor-
phic variable, henc e the term r e- verse p
  • ly-
morphism t yp e. F
  • r
example, a v ariable can b e declared as a p
  • in
ter to an Animal, but actually b e main taining a p
  • in
ter to a Cat. Often
  • ne
is required to form an assignmen t that dep ends up
  • n
the dynamic t yp e, rather than the static t yp e. F
  • r
example,
  • ne
needs to assign the p
  • lymorphic
Animal v ariable to a v ariable
  • f
t yp e Cat. The Ja v a programmer can test the dynamic t yp e
  • f
a v ariable b y means
  • f
the
  • p
erator instanceof, and will p erform the transformation b y using a cast
  • p
erator: Animal a = ... ;
slide-9
SLIDE 9 104 CHAPTER 6. POL YMORPHISM if (a instanceof Cat) Cat c = (Cat) a; Alternativ ely , the Ja v a programmer can explicitly catc h the exception that is thro wn if the con v ersion is illegal: Animal a = ...; try f Cat c = (Cat) a; g catch(ClassCastEx cep ti
  • n
& e) f ... g There is no direct C ++ equiv alen t to the instanceof
  • p
eration. F urthermore, although the syn tax
  • f
the cast
  • p
eration is tak en directly from C ++ , the Ja v a programmer should b e a w are that the seman tics
  • f
the equiv alen t
  • p
eration in C ++ are sligh tly dieren t. The Ja v a cast p erforms a run-time c hec k to ensure the v alidit y
  • f
the con v ersion, and issues W arning C ++ do es not p erform a run time che ck to en- sur e the va- lidity
  • f
c ast c
  • nversions
an exception if illegal. The C ++ cast is en tirely a compile time
  • p
eration, and no c hec k is made at run-time. If the cast is improp er no indication is giv en to the programmer, and an erroneous
  • utcome
will lik ely result: Animal
  • a
= new Dog(); Cat
  • c
= (Cat ) a; c->purr(); // b eha vior is undened Suc h errors can sometimes b e hidden due to the in teraction b et w een the cast
  • p
eration and the rules for virtual and non virtual metho d in v
  • cation.
Note, for example, that if w e had not declared the metho d purr as virtual, the prop er Cat metho d w
  • uld
ha v e b een in v
  • k
ed (since the static t yp e is Cat) despite the fact that the actual v alue held b y v ariable c is a dog. The b eha vior when the metho d is declared as virtual is more dicult to predict;
  • n
man y mac hines it will pro duce a segmen tation fault. T
  • get
around this problem the C ++ language pro vides a dieren t t yp e
  • f
cast, called Note The R TTI is a r e- c ent addition to the C ++ language a dynamic c ast. The dynamic cast is part
  • f
a suite
  • f
functions, called the run-time t yp e information system,
  • r
R TTI. The dynamic cast
  • p
erator is a templated function (see Chapter 9). The template argumen t is the t yp e to whic h con v ersion is desired. Unlik e the normal cast, the dynamic cast
  • p
erator c hec ks the v alidit y
  • f
the con v ersion. If the con v ersion is not prop er, a n ull v alue is yielded. Th us, the result is either a prop erly t yp e- c hec k ed v alue,
  • r
n ull. The programmer can then test the resulting v alue to see if the con v ersion to
  • k
place. In this manner the dynamic cast
  • p
erator com bines the features
  • f
b
  • th
the instanceof
  • p
erator and the cast
  • p
erator in Ja v a. Note T est- ing a p
  • inter
in an if state- ment is the same as test- ing whether
  • r
not the p
  • inter
is nul l Cat
  • c
= dynamic cast<Cat >(a); if (c) printf("variabl e was a cat");
slide-10
SLIDE 10 6.3. DO WNCASTING (REVERSE POL YMORPHISM) 105 else printf("variabl e was not a cat"); If dynamic cast is used with
  • b
ject v alues, instead
  • f
p
  • in
ters, a failure results in a bad cast exception b eing thro wn, rather than a n ull p
  • in
ter. The dynamic cast
  • p
eration w
  • rks
  • nly
with p
  • lymorphic
t yp es, that is, p
  • in
ters (or references) to classes that con tain at least
  • ne
virtual metho d. A static cast is similar, but p erforms no dynamic c hec k
  • n
the result. This is most
  • ften
used to con v ert
  • ne
p
  • in
ter t yp e, for example a void * p
  • in
ter, in to another t yp e: void
  • v
= ...; // w e kno w, from elsewhere, that v is really a cat Cat
  • c
= static cast<Cat >(v); A static cast is not restricted to p
  • lymorphic
t yp es. Tw
  • ther
t yp es
  • f
cast (const cast, R ule Whenever p
  • ssible,
use the R TTI in- ste ad
  • f
stan- dar d unche cke d c ast c
  • nver-
sions and reinterp ret cast) ha v e also b een added to C ++ , but their use is uncommon and they will not b e describ ed here. Ho w ev er, programmers are encouraged to use these new er, more t yp e-safe facilities instead
  • f
the
  • lder
cast mec hanism. 6.3.1 Sim ulating The Dynamic Cast The R TTI is a relativ ely new addition to the C ++ language, and not all compilers will y et supp
  • rt
this feature. Th us, it ma y b e necessary to ac hiev e the eect
  • f
the dynamic cast
  • p
erator without actually using the
  • p
erator. Before the in tro duction
  • f
R TTI,
  • ne
common programmers tric k w as to enco de explicit is-a metho ds in class hierarc hies. F
  • r
example, to test animal v alues to see if they represen t a dog
  • r
cat, w e can write metho ds suc h as the follo wing: class Mammal f public: virtual bool isaDog() f return false; g virtual bool isaCat() f return false; g g; class Dog : public Mammal f public: virtual bool isaDog() f return true; g g; class Cat : public Mammal f public:
slide-11
SLIDE 11 106 CHAPTER 6. POL YMORPHISM virtual bool isaCat() f return true; g g; Mammal
  • fido;
A test, suc h as do!isaDog(), can then b e used to determine if the v ariable do is curren tly holding a v alue
  • f
t yp e Dog. If so, a con v en tional cast can safely b e used to con v ert the quan tit y in to the correct t yp e. By returning a p
  • in
ter rather than an in teger, w e can extend this tric k to com bine b
  • th
the test for sub class t yp e and the con v ersion, whic h is more closely similar to the dynamic cast
  • p
erator in the R TTI. Since a function in the class Mammal is returning a p
  • in
ter to a Dog, the class Dog m ust ha v e a forw ard reference (see Section 5.3). The result
  • f
the assignmen t is either a n ull p
  • in
ter
  • r
a v alid reference to a Dog; so, the test
  • n
the result m ust still b e p erformed but w e ha v e eliminated the need for the cast. This is sho wn as follo ws: class Dog; // forw ard reference class Cat; class Mammal f public: virtual Dog
  • isaDog()
f return 0; g virtual Cat
  • isaCat()
f return 0; g g; class Dog : public Mammal f public: virtual Dog
  • isaDog()
f return this; g g; class Cat : public Mammal f public: virtual Cat
  • isaCat()
f return this; g g; Mammal
  • fido;
Dog
  • lassie;
A statemen t suc h as lassie = fido->isaDog();
slide-12
SLIDE 12 6.4. NAME RESOLUTION 107 can then always b e p erformed. It will result in the v ariable lassie holding a non-n ull v alue
  • nly
if do indeed held a v alue
  • f
class Dog. If do did not hold a dog v alue, then a n ull p
  • in
ter v alue will b e assigned to the v ariable lassie. if (lassie) ... fido was indeed a dog else ... assignment did not work ... fido was not a dog While it is p
  • ssible
for the programmer to implemen t this, the disadv an tage
  • f
this tec hnique for p erforming do wncasting (sometimes called rev erse p
  • lymorphism)
is that it requires adding metho ds to b
  • th
the paren t and the c hild classes. If there are man y c hild classes inheriting from
  • ne
common paren t class, the mec hanism can b ecome un wieldy . If making c hanges to the paren t class is not p ermitted this tec hnique is not p
  • ssible.
6.4 Name Resolution As part
  • f
  • b
ject
  • rien
ted metho d in v
  • cation
a message selector m ust b e b
  • und
to the Define Name r esolu- tion is matching a function b
  • dy
to a function name appropriate function b
  • dy
. The tec hniques used b y Ja v a and C ++ for this purp
  • se
are similar, but not iden tical. Consider, for example, the follo wing t w
  • class
denitions in Ja v a: class Parent f public void test (int i) f System.out.printl n( "p are nt test"); g g class Child extends Parent f public void test (int i, int i) f System.out.print ln( "c hil d two arg test"); g public void test (Parent p) f System.out.print ln( "c hil d
  • bject
test"); g g The name space for the class P a rent in tro duces a new function, named test, that tak es a single in teger argumen t. The class Child builds
  • n
this name space, and adds to this t w
  • ther
denitions for the function test. Eac h
  • f
these can b e easily distinguished from the
  • riginal
b y the n um b er
  • r
t yp e
  • f
argumen ts, so there is no p
  • ssibilit
y
  • f
confusion. If w e no w pro vide an in v
  • cation,
suc h as the follo wing: Child c = new Child();
slide-13
SLIDE 13 108 CHAPTER 6. POL YMORPHISM c.test(3); the compiler selects the function with matc hing argumen ts, in this case the function inherited from the class P a rent. No w consider an equiv alen t C ++ program: class Parent f public: void test (int i) f printf("parent test"); g g; class Child : public Parent f public: void test (int i, int i) f printf("child two arg test"); g void test (Parent & p) f printf("child
  • bject
test"); g g; If w e try in v
  • king
the function inherited from the paren t, w e will get a compiler error: Child
  • c
= new Child(); c->test(3); // will generate compiler error The explanation for this b eha vior is that the C ++ language main tains separate but link ed descriptions
  • f
eac h
  • f
the v arious name scop es. In this case, there are at least three dieren t name scop es: the global scop e, the scop e for class P a rent, and the scop e for class Child. T
  • resolv
e a name, suc h as test, the compiler p erforms a t w
  • step
pro cess. Step
  • ne
is to searc h for the rst enclosing scop e in whic h the name is dened. In this case, that w
  • uld
b e the scop e for Child. Step t w
  • is
to then try to matc h the name with a function dene d in that sc
  • p
e. In this case, there are
  • nly
t w
  • p
  • ssibilities,
neither
  • f
whic h will w
  • rk.
Being unable to nd a matc hing function, a compiler error is rep
  • rted.
T
  • circum
v en t this, the C ++ programmer should redene an y inherited names that are R ule R e- dene any inherite d names that ar e
  • ver-
lo ade d with dier ent typ e signatur es b eing
  • v
erloaded with new meanings. This can b e done with a simple in-line function, as in the follo wing: class Child : public Parent f public: void test (int i) f Parent::test(i); g // redene inherited metho d void test (int i, int i) f printf("child two arg test"); g void test (Parent & p) f printf("child
  • bject
test"); g g;
slide-14
SLIDE 14 6.5. A F OREST, NOT A TREE 109 No w all three metho ds will b e dened in the Child scop e, and will hence b e a v ailable for use. 6.5 A F
  • rest,
not a T ree In Ja v a all
  • b
jects descend ultimately from the base class Object. This has the adv an tage
  • f
ensuring that ev ery
  • b
ject p
  • ssesses
some minimal functionalit y , namely the metho ds pro vided b y class Object. These
  • p
erations include the abilit y to get the class
  • f
an
  • b
ject, con v ert an
  • b
ject in to a string represen tation, test an
  • b
ject for equalit y against another
  • b
ject, and compute the hash v alue for an
  • b
ject. Classes in C ++ are not part
  • f
a single hierarc h y . If a class is not dened as inheriting Note In C ++ ther e is no class that is anc estor to al l classes from another class, then it is the ro
  • t
  • f
its
  • wn
hierarc h y , and pro vides
  • nly
the b eha vior dened b y the class description. Th us, a t ypical C ++ program con tains a n um b er
  • f
dieren t class hierarc hies, eac h indep enden t
  • f
the
  • thers.
In Ja v a the class Object is
  • ften
used to declare univ ersal generic
  • b
jects, v alues that can hold an y
  • ther
  • b
ject t yp e. Since C ++ do es not ha v e a single ro
  • t
class, there is no exact equiv alence. F requen tly template classes (see Chapter 9) eliminate the need for generic Object v ariables. Ho w ev er, where they cannot b e a v
  • ided,
void p
  • in
ters can
  • ften
b e made to serv e the same purp
  • se.
A v ariable declared as a p
  • in
ter to a void v alue can b e assigned an y
  • ther
p
  • in
ter t yp e, regardless
  • f
the t yp e
  • f
  • b
ject the p
  • in
ter references. Animal
  • a
= new Dog(); void
  • v
= a; // assign v p
  • in
ter to an animal Just as a cast m ust b e used to do wncast an Object v alue in Ja v a, a dynamic cast (see Section 6.3) should b e used to con v ert a v
  • id
p
  • in
ter v alue bac k in to the
  • riginal
t yp e. Dog
  • dd
= dynamic cast<Dog >(v); Note, ho w ev er, that the dynamic cast
  • nly
w
  • rks
if the p
  • in
ter references a class that con tains at least
  • ne
virtual metho d. 6.6 Virtual Destructors A destructor (see Chapter 4) is a metho d that is in v
  • k
ed immediately b efore a v ariable is to b e deleted. When p
  • lymorphic
v ariables are used, a concern is whether
  • r
not a destructor function should b e declared as virtual. T
  • illustrate,
let us add destructor functions to the classes presen ted earlier in Figure 6.2: class Animal f
slide-15
SLIDE 15 110 CHAPTER 6. POL YMORPHISM virtual Animal () f printf("goodbye animal"); g ... g; ... class Cat : public Mammal f Cat () f printf("goodbye cat"); g ... g; No w imagine w e create and delete a p
  • lymorphic
v ariable, as follo ws: Animal
  • a
= new Cat(); delete a; If the destructor in Animal is declared virtual, as sho wn, then b
  • th
the destructors in class Animal and class Cat will b e executed. If the virtual designation is
  • mitted,
then
  • nly
the metho d in class Animal will b e p erformed. If the destructor is
  • mitted
from Animal altogether, then the metho d from class Cat will not b e p erformed, whether
  • r
not it is declared virtual. A go
  • d
rule
  • f
th um b is to declare a destructor as virtual if there are an y
  • ther
virtual R ule De- clar e a vir- tual destruc- tor if a class has any vir- tual metho ds metho ds. A destructor should b e pro vided in this case, ev en if it p erforms no useful actions, as
  • therwise
destructors from c hild classes ma y not b e executed. Note also
  • ne
more dierence b et w een destructors and nalize metho ds in Ja v a. A nalize metho d should alw a ys explicitly in v
  • k
e the nalize metho d that it inherits from its paren t class. A destructor will do this automatically , and no explicit call is required. 6.7 Priv ate Inheritance Y
  • u
will ha v e undoubtedly noticed ho w the k eyw
  • rd
public is used to indicate inheritance in C ++ , rather than the k eyw
  • rd
extends as in Ja v a. While public inheritance is the most common, it is also p
  • ssible
to p erform protected
  • r
priv ate inheritance. When
  • ne
  • f
these
  • ther
forms are used, the visibilit y
  • f
data elds and metho ds is the maxim um
  • f
their declared mo diers and the mo dier used for inheritance. That is, if inheritance is p rotected, then elds declared as public in the paren t class b ecome p rotected in the c hild class. If inheritance is p rivate, then elds declared either as public
  • r
p rotected in the paren t b ecome p rivate in the c hild class. T
  • understand
the signicance
  • f
this distinction, imagine the public features
  • f
a paren t class as
  • wing
through a c hild class, to b ecome public features
  • f
the c hild class as w ell:
slide-16
SLIDE 16 6.7. PRIV A TE INHERIT ANCE 111 public H H H H H H H H H j In a p rivate inheritance, the public (and p rotected) features
  • f
the paren t class are a v ailable for use in the c hild class, but do not b ecome part
  • f
the c hild class in terface. In eect, they do not
  • w
through the c hild class, but are instead stopp ed at that lev el: public H H H H H H j T
  • illustrate
wh y y
  • u
migh t w an t to use this feature, imagine that y
  • u
need to build a stac k abstraction, and y
  • u
ha v e already a list class that y
  • u
w an t to use as the underlying con tainer. One p
  • ssibilit
y is to simply use inheritance, and deriv e the stac k from the list: class Stack : public List f // assume elemen ts are in tegers public: push (int val) f addToFront(val) ; g pop () f removeFirstEleme nt (); g top () f return firstElement(); g A problem with this abstraction is that it is to
  • p
  • w
erful, it pro vides the user
  • f
the stac k with to
  • man
y
  • p
erations. In particular, there is no w a y to k eep the user from accessing the List
  • p
erations, ev en when they are not appropriate. F
  • r
example, someb
  • dy
migh t directly add
  • r
remo v e and elemen t directly from the b
  • ttom
  • f
a stac k. By sp ecifying a p rivate inheritance, w e a v
  • id
this p
  • ten
tial misuse. The features
  • f
the R ule Use private inheritanc e when the child class is not a mor e sp e- cialize d form
  • f
the p ar ent class paren t class List, ev en if they are declared public
  • r
p rotected, are not passed through to b ecome part
  • f
the Stack in terface. Th us, the
  • nly
features are those explicitly describ ed: class Stack : private List f public: push (int val) f addToFront(val) ; g
slide-17
SLIDE 17 112 CHAPTER 6. POL YMORPHISM pop () f removeFirstEleme nt (); g top () f return firstElement(); g But if public inheritance p ermitted to
  • man
y
  • p
erations to b ecome attac hed to the new abstraction, simply declaring a priv ate inheritance can b e to
  • restrictiv
e. There ma y b e some
  • p
erations that
  • ne
w an ts to p ermit. F
  • r
example, the metho ds that c hec k the size
  • f
the list are still appropriate for the stac k abstraction. W e can sp ecify that these new features should con tin ue to b e part
  • f
the Stac k abstraction b y means
  • f
the using k eyw
  • rd.
The using k eyw
  • rd
p ermits individual items from the paren t class to b e selected and attac hed to the in terface for the c hild class, while ltering
  • ut
all
  • ther
  • p
erations. class Stack : private List f public: push (int val) f addToFront(val) ; g pop () f removeFirstEleme nt (); g top () f return firstElement(); g using isEmpty(); using int size(); g; 6.8 Inheritance and Arra ys There are a n um b er
  • f
situations where it could b e argued that the Ja v a seman tics are an impro v emen t
  • v
er the C ++ seman tics, most
  • ften
b ecause the C ++ seman tics are incomplete
  • r
undened. Ho w ev er, there is
  • ne
curious situation where the Ja v a seman tics seem more confused than their C ++ coun terpart. This concerns an in teraction b et w een inheritance and arra ys. Assume w e ha v e declared an arra y
  • f
Dog v alues. Ja v a p ermits this arra y to b e assigned to a v ariable that is declared as an arra y
  • f
the paren t class: Dog [ ] dogs = new Dog[10]; // an arra y
  • f
dog v alues Animal [ ] pets = dogs; // legal In eect, Ja v a is asserting that the t yp e Dog[ ] (that is, arra y
  • f
dogs) is a subt yp e
  • f
the t yp e Animal[ ]. T
  • see
what confusion can then arize, imagine the follo wing assignmen t: pets[2] = aCat; // is this legal? On the face
  • f
it, it w
  • uld
seem to certainly b e legal to reassign an elemen t in the arra y to no w hold a Cat v alue. After all, the arra y is declared as an arra y
  • f
animals, and a Cat
slide-18
SLIDE 18 6.9. O VERLO ADING 113 is an animal. But remem b er that the arra y in question shares a reference with an arra y
  • f
dog v alues, and b y p erforming this assignmen t w e actually con v ert
  • ne
elemen t in the Dog arra y in to a cat. T
  • prev
en t this, Ja v a actually p erforms a run-time c hec k
  • n
assignmen ts to arra ys
  • f
  • b
jects. C ++ ,
  • n
the
  • ther
hand, tak es a simpler approac h, and simply asserts that ev en though a Dog ma y b e an Animal, there is no inheritance
  • r
subt yp e relationship b et w een an arra y
  • f
Dog and an arra y
  • f
Animal. 6.9 Ov erloading A function is said to b e
  • verlo
ade d when there are t w
  • r
more function b
  • dies
asso ciated Define A n
  • ver-
lo ade d name has mor e than
  • ne
me aning with a single function name. Ov erriding is
  • ne
form
  • f
  • v
erloading, ho w ev er
  • v
erloading can
  • ccur
ev en without
  • v
erriding. W e sa w an example
  • f
this in an earlier section, whic h included the follo wing class denition: class Child : public Parent f public: void test (int i) f Parent::test(i); g // redene inherited metho d void test (int i, int j) f printf("child two arg test"); g void test (Parent & p) f printf("child
  • bject
test"); g g; Here there are three dieren t v ersions
  • f
the test function, distinguished b y the compiler b y the n um b er and t yp e
  • f
argumen ts used in the function in v
  • cation.
Constructor functions are
  • ften
  • v
erloaded in this fashion, ho w ev er an y function can b e so dened. The Ja v a programmer should b e a w are that almost all C ++
  • p
erators can also b e
  • v
er- loaded. F
  • r
example, if w e w an ted to pro vide a meaning for the
  • p
erations
  • f
\adding" t w
  • cats
  • r
t w
  • dogs,
w e could do so as follo ws: Dog
  • perator
+ (Dog
  • left,
Dog
  • right)
f // return a new Dog v alue // that is the sum
  • f
the paren ts return new Dog(); g Cat
  • perator
+ (Cat
  • left,
Cat
  • right)
f return new Cat(); g
slide-19
SLIDE 19 114 CHAPTER 6. POL YMORPHISM These functions w
  • uld
p ermit a dog v alue to b e added to another dog,
  • r
a cat to a cat, but not p ermit a cat to b e added to a dog. Op erators can b e dened either as
  • rdinary
functions (as sho wn here)
  • r
as mem b er functions. This will b e discussed in detail in the next c hapter. T est Y
  • ur
Understanding 1. What is a p
  • lymorphic
v ariable? 2. Using the concepts
  • f
static and dynamic t yp e, explain the eect
  • f
the mo dier virtual. 3. Ho w can y
  • u
prin t the name
  • f
the class for an
  • b
ject v alue b eing held b y a p
  • lymorphic
v ariable? 4. What is a pure virtual metho d? 5. What is a do wncast? 6. What do the initial R TTI stand for? 7. What is a dynamic cast? Ho w do es it dier from a normal cast? 8. Explain ho w the name resolution algorithm used in C ++ diers from that
  • f
Ja v a. 9. Ho w are exceptions tied to function names in C ++ ? Ho w is this dieren t from Ja v a? 10. What are some
  • f
the adv an tages Ja v a deriv es from ha ving all
  • b
ject t yp es inherit from the same base class (namely , Object)? 11. What is a virtual destructor? When is suc h a concept imp
  • rtan
t? 12. Ho w do es priv ate inheritance dier from normal inheritance? 13. What is an
  • v
erloaded name? Ho w is it dieren t from an
  • v
erridden metho d name?