implementing inheritance polymorphism and virtual...
TRANSCRIPT
Polymorphism and VirtualFunctionsChapter 11
Copyright © 1998-2004 Delroy A. Brinkerhoff. All Rights Reserved.CS 1220 Chapter 11 Slide 1 of 30
Implementing InheritanceAnd accessing member data
a
b
c
d
e
f
bar object
foo
B
class foo{
private:int a;int b;int c;
};
class bar : public foo{
private:int d;int e;int f;
};
a = Bb = B + sizeof(a)c = B + sizeof(a)
+ sizeof (b)
d = B + sizeof(foo)e = B + sizeof(foo)
+ sizeof(d)f = B + sizeof(foo)
+ sizeof(d)+ sizeof(e)
bar* B = new bar;
CS 1220 Chapter 11 Slide 2 of 30
Subobject InitializationConstructor calls
P Initialization< Inheritance: use class name< Composition: use object (attribute) name< Built-in: use variable (attribute) name
class foobar : public foo{
private:bar B;int C;
public:foobar(int a, int b, int c) : foo(a), B(b), C(c) { }
};CS 1220 Chapter 11 Slide 3 of 30
Overriding Inherited FunctionsA bar “is like a” foo– a simile
class foo{
public:void func1( );void func2( );
};
bar B;
B.func1( ); // bar::func1 – overrides fooB.func2( ); // foo::func2B.foo::func1(); // foo::func1
class bar : public foo{
public:void func1( ) { foo::func1( ); }
};
CS 1220 Chapter 11 Slide 4 of 30
UpcastingAllowed and disallowed type conversions
Parent Class
Child Class
Safe Explicit cast
class Parent { }class Child { }
Child C;Parent* Pptr = &C; // safe upcastChild* Cptr = (Child *) Pptr; // risky down cast
Parent
Child
CS 1220 Chapter 11 Slide 5 of 30
Subobject Location and CastingCompare with slide 2
a
b
c
d
e
f
bar object
bar* B = new bar;foo* F = B;
FB
foo* F1 = new foo;bar* B1 = (bar *)F;
a
b
c
foo objectF1B1
foo
bar
e = B + sizeof(foo) + d
what isB1 + sizeof(foo) + d ?
CS 1220 Chapter 11 Slide 6 of 30
Member Functions and CastingCompile-time binding
class foo{
public:void func( );
};
bar B;bar* barPointer = &B;foo* fooPointer = &B; // up cast
barPointer->func( ); // bar::funcfooPointer->func( ); // foo::func
class bar : public foo{
public:void func( );
};
CS 1220 Chapter 11 Slide 7 of 30
Early BindingStatic or compile-time binding
PCompiler identifies the correct function and binds (i.e.,generates a “direct call”)
PApplies to< “Ordinary functions”< Member functions< Overloaded functions (member and nonmember)< Functions associated with embedded objects< Functions belonging to the objects and sub-objects in an inheritance
hierarchy
CS 1220 Chapter 11 Slide 8 of 30
The Early Binding ProblemDynamic binding
positioncolor
draw( )erase( )move( )
Shape
radius
draw( )erase( )
Squareside
draw( )erase( )
Triangleside1side2side3
draw( )erase( )
Circle
Shape* S
Exact shape selecteddynamically at runtime,perhaps in response touser input.
S->draw( ); Which draw method iscalled?
// For example – the result of early binding
Circle C;
Shape* S = &C;S->draw( ); //Shape::draw
CS 1220 Chapter 11 Slide 9 of 30
Solution?The old, functional way
PAdd an enum attribute that identifies each object< enum { Shape, Circle, Rectangle, Triangle };
PUse a switch statement to call the correct draw function
PAdding a new Ellipse shape requires “touching”< The enum< Every location where the draw function is called (add a case)
switch (shape){ case Shape : ...
case Circle : ...case Rectangle : ...case Triangle : ...
}
CS 1220 Chapter 11 Slide 10 of 30
Polymorphism“Many shapes”
PThe ability of similar objects to respond differently to thesame message
PSelecting the correct function is deferred until runtime and isbased on the object
P Implements extensibility and dynamic code reusePRequires< Inheritance (direct inheritance or common ancestor)< Address variables (pointers or references)< Upcast to common ancestor
PActivated in C++ with the virtual keyword
CS 1220 Chapter 11 Slide 11 of 30
Late BindingRun-time or dynamic binding, also dynamic dispatch
PSelect the correct function only after the object type is knownP Implements the concept of polymorphismPPolymorphic functions are declared virtual in the base class< Optionally may be declared virtual in base classes (they are virtual
even if the “virtual” keyword is not specified)Pvirtual functions “expect” to be overridden
CS 1220 Chapter 11 Slide 12 of 30
Polymorphic SolutionThe new way of thinking
Circle C;
Shape* S = &C;S->draw( ); //Circle::draw
positioncolor
draw( )erase( )move( )
Shape
radius
draw( )erase( )
Squareside
draw( )erase( )
Triangleside1side2side3
draw( )erase( )
Circle
class Shape{
public:...
virtual void draw( );};
CS 1220 Chapter 11 Slide 13 of 30
Polymorphism and Code ReusabilityOne benefit
PAdding a new Ellipse shape now requires< Declaring the Ellipse class, derived from Shape< Defining the member functions and compiling them to object code< Re-linking the program
PDoes not require changing the function callsPNo existing source code is copied or “soiled” (source may not
even be available)
CS 1220 Chapter 11 Slide 14 of 30
Determining Which Method Is CalledPolymorphism vs non-polymorphism
PShape* S = new Circle;Pvoid render(Shape* S);< render(new Shape);< render(new Circle);
PNon-polymorphic call< Function belongs to the class named on the left hand side of the
assignment operatorPPolymorphic call< Function belongs to the instantiated class on the right hand side of
the assignment operatorPExample< Non-polymorphic: S->draw( ) // Shape draw function< Polymorphic: S->draw( ) // Circle draw function
CS 1220 Chapter 11 Slide 15 of 30
Quick QuizUsing polymorphism
PWhich functions are called?class Parent{
public:void funcA( );
virtual void funcB( );void funcC( );
};
class Child : public Parent{
public:void funcA( );
virtual void funcB( );};
int main( ){
Parent* P1 = new Parent;Parent* P2 = new Child;Child* C = new Child;
P1->funcA( ); //_______________P1->funcB( ); //_______________P1->funcC( ); //_______________P2->funcA( ); //_______________P2->funcB( ); //_______________P2->funcC( ); //_______________C->funcA( ); //_______________C->funcB( ); //_______________C->funcC( ); //_______________
}CS 1220 Chapter 11 Slide 16 of 30
Implementing PolymorphismDone by the compiler
PAddresses of virtualfunctions put in VTABLE
POne VTABLE per classPEvery object contains a
“secret” pointer to theclasses’ VTABLE
PVPTR is initialized by theconstructor
Objects VTABLEsShape::drawShape::erase
Circle::drawCircle::erase
Rectangle::drawRectangle::erase
Triangle::drawTriangle::erase
Shape
Circle
Rectangle
Triangle
vptr
vptr
vptr
vptr
shape* ptr
CS 1220 Chapter 11 Slide 17 of 30
Polymorphism and ConstructorsThe consequences
PCompiler adds to user-defined constructor or creates adefault constructor to initialize VPTR
PConstructors called from the base to most derived class;VPTR updated by each constructor
PConstructors only call local versions of virtual functions< Only base-class objects initialized< VPTR may not point to the correct VTABLE yet
PConstructors cannot be virtual
CS 1220 Chapter 11 Slide 18 of 30
Polymorphism and DestructorsThe consequences
PDestructors called from most derived to basePDestructors can be virtualP If a class has virtual functions, it should have a virtual
destructorPExample< Shape* figure = new Circle;< delete figure;
P If the destructor is pure virtual (see next slide), it must alsohave a body
PDestructors only call local versions of virtual functions
CS 1220 Chapter 11 Slide 19 of 30
Cost of PolymorphismNo free lunches
PVTABLE for every polymorphic classPVPTR embedded in every polymorphic objectP Indirect function accessPvirtual functions cannot be inline< virtual and inline keywords are incompatible< Functions created inline as part of the class declaration are
“flushed” to memoryPPolymorphism is optional in C++
CS 1220 Chapter 11 Slide 20 of 30
Abstract Base ClassesWhat does it mean to draw a Shape – what does a Shape look like?
PAbstract class< Has one or more pure virtual functions
PConcrete classes< Inherit Shape position and color< Inherit Shape move< Must override all pure virtual functions
or become abstract
positioncolor
draw( )erase( )move( )
Shape
radius
draw( )erase( )
Squareside
draw( )erase( )
Triangleside1side2side3
draw( )erase( )
Circle
class Shape{
public:virtual void draw( ) = 0;
};
CS 1220 Chapter 11 Slide 21 of 30
Abstract ClassesClasses that cannot be instantiated
PConcrete classes may be instantiatedPAbstract classes cannot be instantiatedPThey only make sense in the context of inheritance< Organize features common to many classes< Declare an operation (protocol, interface) that each subclass must
provide< The origin class is the topmost defining class; it defines the protocol
PAbstract (pure virtual) functions must be overridden inconcrete classes
PSome abstract classes appear naturally in the problemdomain; others are abstractions artificially introduced forcode reuse or from implementation requirements
CS 1220 Chapter 11 Slide 22 of 30
The Copy ConstructorReplacing the compiler-provided default copy constructor
PCopy constructor is used to pass and return objects< C++ default copy constructor does pass and return by value (i.e.,
bit-wise copy)PBit-wise copy is easy but has two potential problems< Time consuming to copy large objects< Generally does not handle pointers correctly
PBig classes:class Big { .... };
Big function(Big var) { ...; return var; }Big a, b;a = function(b); // copies b to var and var to a
CS 1220 Chapter 11 Slide 23 of 30
Definition of Copy?What does it mean to copy an object?
class Employee{ private:
Date hire;};
1996/09/03hire
1996/09/03hire
class Employee{ private:
Date* hire;};
1996/09/03
hire
hire
CS 1220 Chapter 11 Slide 24 of 30
Overloading the Copy ConstructorDefining the meaning of copy
PCopy constructor must copy all data members
class Employee{
private:double salary;Date* hire;Address* addr;
public:Employee(Employee& old){
salary = old.salary;hire = new Date(old.hire);addr = new Address(old.addr);
}};
CS 1220 Chapter 11 Slide 25 of 30
The Assignment OperatorReplacing the compiler-provided default assignment operator
PAlways created for every class< The default does a bit-wise copy for each data member< When overloaded by the user, the user must define what it means
to assign one object to anotherPLike the copy constructor, except< The destination (left hand side) may have a “value” that must be
discarded prior to the new assignment< Should test for assigning an object to itself (i.e., A = A;)< Can have a return value (NOTE: the return value is irrelevant to the
assignment operation and is only needed for chaining assignment:A = B = C;
< operator= cannot be overloaded outside of a class
CS 1220 Chapter 11 Slide 26 of 30
Overloading operator=Replacing the default assignment operator
class Employee{
private:double salary;Date* hire;Address* addr;
public:Employee& operator=(Employee& rhs)
{if (&rhs == this) return *this; // for A = A.if (hire != 0) delete hire; // A held an object.if (addr != 0) delete addr; // ditto.salary = old.salary; // start newhire = new Date(old.hire); // assignment.addr = new Address(old.addr);
}};
CS 1220 Chapter 11 Slide 27 of 30
Quick QuizWhat is an appropriate return value type?
PThe overloaded assignment operator returns a reference andhas the general form:< X& X::operator=(X&)
Poperator+ does not return a reference (which is commonfor arithmetic operators) and has the general form:< X X::operator+(X&)
PWhy does the assignment operator return a reference whilethe arithmetic operators return an object?
PHint: consider the operands< which one exists before the call and one is created by the function?< remember that A = B is equivalent operator=(A, B)
CS 1220 Chapter 11 Slide 28 of 30
Miscellaneous operator= FactsFor the “bar know-it-all”
PThe return type of operator= is only used for embeddingassignment statements in larger statements:< A = B = C is equivalent to operator=(A, operator=(B, C))< The expression is executed as A = (B = C); the operation B + C
returns the address of B, which becomes the argument to the nextassignment operation
PDistinguishing the copy constructor from the assignmentoperator is not always as straightforward as you might think:< foo A;< foo B = A; // copy constructor< B = A; // assignment operator
CS 1220 Chapter 11 Slide 29 of 30
Other Cases of Return-By-ReferenceIncreasing flexibility
class Stack{
private:int stackmem[100];
public:int& operator[ ](int index){
return stackmem[index];}
};
Stack S;
S[5] = 10; // can be an lvalueS[0] = S[5]; // can be an rvalue
CS 1220 Chapter 11 Slide 30 of 30