Top Banner
. Virtual Classes & Polymorphism
38

. Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Dec 18, 2015

Download

Documents

Elmer Webster
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

.

Virtual Classes & Polymorphism

Page 2: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Example (revisited)

We want to implement a graphics system We plan to have lists of shape. Each shape

should be able to draw it self, compute its size, etc.

Page 3: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Solution #1class Shape {

public:

enum Type { Square, Circle, Triangle };

Shape( Type t, Point Center,

double width, double height);

void Draw();

double Area();

private:

Type m_type;

Point m_center;

};

Page 4: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Solution #1

This solution gives a nice “wrapping” to the solution we consider in C

It does not solve the problems of that solution Lack of extendibility

Page 5: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Solution #2 – different classesclass Square {

public:

void Draw();

double Area();

};

class Circle {

public:

void Draw();

double Area();

};

Page 6: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Solution #2 – Discussion

Each shape has its own implementation We can easily add new shapes

However, Shapes are different types One cannot view them as part of the same

class

Page 7: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Solution #3 - hierarchyclass Shape {

public:

void Draw();

double Area();

};

class Square: public Shape {

public:

void Draw();

double Area();

};

class Circle: public Shape {

public:

void Draw();

double Area();

};

Page 8: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Solution #3

Now we can write code such as:

Shape* MyShapes[2];

MyShapes[0] = new Circle();

MyShapes[1] = new Square();

What will happen when we callMyShapes[0]->Draw();

Lets test … see Shapes.cpp.

Page 9: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

What is going on?

When we write:Circle circle;

circle.Draw();

The compiler calls Circle::Draw()

When we write:Shape* p = new circle();

p->Draw();

The compiler calls Shape::Draw()Why? *p has type Shape

Page 10: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Class Hierarchyclass Base {

public:

void foo();

void bar();

};

class Derived: public Base {

public:

void bar();

};

Derived obj;

obj.foo();

Calls Base::foo() Derived does not

implement this method

obj.bar(); Calls Derived::bar() Two implementations,

the more specific is used

Page 11: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Inheritance & Overloading

Derived inherits the method foo() from Base

The inherited class to use methods of the base class

Derived overloads the implementation of bar()

This mechanism allows an inherited class to specialize the implementation

Page 12: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Static resolution

How does the compiler determine which method to call?

Static Resolution: Based on the type of the variable.

Not the type of the object! The compiler finds the most specific

implementation of the method, and calls it

Page 13: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Static resolution in our example

Circle* circle = new Circle(1,1,2);

Square* square = new Square(2,2,1);

Shape* MyShapes[2];

MyShapes[0] = circle;

MyShapes[1] = square;

circle->Draw(); // Calls Circle::Draw()

square->Draw(); // Calls Square::Draw()

MyShapes[0]->Draw(); // Calls Shape::Draw()

MyShapes[1]->Draw(); // Calls Shape::Draw()

Page 14: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Dynamic Resolution

This clearly not what we want to in this example

More desirable here is

Dynamic resolution: Based on the type of the object Determined at run time

[Java Like]

Page 15: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Dynamic Resolution in C++

The virtual keyword states that the method can be overloaded in a dynamic manner.

class Base {

public:

virtual void bar();

}

class Derived: public Base {

public:

virtual void bar();

}

Page 16: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Solution #4: dynamic resolution

Returning to the shapes example, using virtual methods gives the desired result

See Shapes-virtual.cpp

Page 17: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Virtual Methods

Class Base defines a virtual method foo() The resolution of foo() is dynamic in all

subclasses of Base If the subclass Derived overloads foo(),

then Derived::foo() is called If not, Base::foo() is called

[See nested.cpp]

Page 18: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Underneath the Hood: Inheritance

class Base {

private:

double m_x;

int m_a;

};

class Derived

: public Base {

private:

double m_z;

};

class Base a;

class Derived b;

m_x

m_a

m_z

m_x

m_a

a:

b:Base

Page 19: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Pointing to an Inherited Class

class Derived b;

class Base* p = &b;

When using *p, we treat b as though it was a Base object

The compiler cannot know if *p is from a derived class or not.

m_x

m_a

m_z

b:

p:

Page 20: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Implementation of Virtual Methods

Possible approach: If foo() is a virtual method, then each object

has a pointer to the implementation of foo() that it uses

Essentially the solution we used in our C implementation

Cost: Each virtual method requires a pointer

Large number of virtual methods

waste of memory

Page 21: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Implementation of Virtual Methods

Alternative solution: Each object has a pointer to an array of

function pointer This array points to the appropriate functions

Cost: For each class, we store one table Each object contains one field that points to

the right table

Page 22: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Exampleclass A { public: virtual void f1(); virtual void f2(); int m_a;};

class B: public A { public: virtual void f1(); virtual void f3(); void f4();

int m_b;};… A a1, a2; B b;

class A { public: virtual void f1(); virtual void f2(); int m_a;};

class B: public A { public: virtual void f1(); virtual void f3(); void f4();

int m_b;};… A a1, a2; B b;

void A::f1{ //...};

void A::f1{ //...};

void A::f2{ //...};

void A::f2{ //...};

void B::f1{ //...};

void B::f1{ //...};

VTBLs

A

B

<vtbl>

m_a

a1:

<vtbl>

m_a

m_b

b:

<vtbl>

m_a

a1:

void B::f3{ //...};

void B::f3{ //...};

f1

f2

f3

f1

f2

Page 23: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Virtual - Recap

Virtual controls whether to use static or dynamic resolution

Once a method is virtual, it must remain so throughout the hierarchy

Calling a virtual method is more expensive than standard calls Two pointers are “chased” to get to the

address of the function

Page 24: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Destructors & Inheritance

class Base {

public:

~Base();

};

class Derived : public Base {

public:

~Derived();

};

Base *p = new Derived;

delete p;

Which destructor is called? [see destruct.cpp]

Page 25: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Virtual Destructor

Destructor is like any other method The example uses static resolution, and

hence the wrong destructor is called To fix that, we need to declare virtual

destructor at the base class! See destruct-virt.cpp

Once you declare virtual destructor, derived class must declare a destructor

Page 26: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Polymorphism & Inheritance

C++ allows to use class hierarchy to implement polymorphic code

Points of care: Choice of virtual methods

Run time considerations Use of virtual destructor for base class

Page 27: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Shapes & Sizes

Revisiting our example, we writeclass Shape {

public:

virtual ~Shape(); // Virtual destructor

virtual void Draw(); // Virtual method

virtual double Area(); // Also

};

How do we implement Shape::Draw() ?

Page 28: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Inheritance & Interfaces In this example, we never want to deal with

objects of type Shape Shape serves the role of an interace

All shapes need to be specific shapes that are instances of derived classes of Shape

How do we enforce this?Simple mechanism:void Shape::Draw(){assert(false); // we should never call this method

}

Page 29: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Pure Virtual Classes

We can specify that Shape::Draw() does not exist

class Shape {

public:

virtual ~Shape(); // Virtual destructor

virtual void Draw() = 0; // pure virtual

virtual double Area() = 0; // Also

};

Page 30: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Pure Virtual

We cannot create objects of a Pure Virtual class

Shape* p; // legal

Shape s; // illegal

Circle c; // legal

p = &c; // legal

p = new Shape; // illegal

Page 31: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Virtual Methods - Tips

If you have virtual methods in a class, always declare its destructor virtual

Never call virtual methods during construction and destruction

Use virtual methods Duplicate() and Create() for implementing “virtual constructors”

Use pure virtual classes to define interfaces Use inheritance with care: Be sure that this

is the appropriate solution

Page 32: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Post Quiz issues….

Things to brush up on: Preprocessor vs. Compiler #define and how it works Compiler vs. Linkage

Page 33: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Example void main()

{

(1) int *y = (int*)malloc( 3*sizeof(int) );

(2) int x[] = {1,2,3};

(3) int ** pp = NULL;

(4) int *z = y;

}

A space on the memory heap was allocated in the following lines:

a. 1

b. 2

c. 3

d. 4

Page 34: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Another

int *ip = (int*)malloc(100*sizeof(int));

(*ip) += 30;

free(ip);

1 This code will generate a compilation error.

2 This code can generate unpredictable run-time behavior.

3 No error would occur if we only check if ip equals NULL before calling the "free" function

4 The code contains no error.

Page 35: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Something else….

char s[] = {'p','l','a','b'};

What will be returned by calling strcmp(s,"plab")?

1. a negative number

2. 0

3. a positive number

4. We cannot know for sure

Page 36: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Almost Last Examplestruct MyStruct {

int x[3];

};

void f(MyStruct s)

{

s.x[0] = 15; s.x[1] = 16; s.x[2] = 17;

}

int main()

{

MyStruct s;

f(s);

printf("%d %d %d\n", s.x[0], s.x[1], s.x[2]);

}

Page 37: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Similar but not quite…struct MyStruct {

int x[3];

};

void f(MyStruct* s)

{

s->x[0] = 15; s->x[1] = 16; s->x[2] = 17;

}

int main()

{

MyStruct s;

f(&s);

printf("%d %d %d\n", s.x[0], s.x[1], s.x[2]);

}

Page 38: . Virtual Classes & Polymorphism. Example (revisited) u We want to implement a graphics system u We plan to have lists of shape. Each shape should be.

Final Exampletypedef void (*myfunc)(int*);

void foo(int * x) {

x[0] += 2;

}

void bar( int * x ) {

x[1] += 2;

}

main()

{

myfunc funcs[2] = {

foo,

bar

};

int arr[] = {3,4,5};

(funcs[0])(arr);

(funcs[1])(arr+1);

printf("%d %d %d\n",arr[0],arr[1],arr[2]);

}