Top Banner
Polymorphism From now on we will use g++!
31

Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Dec 19, 2015

Download

Documents

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

PolymorphismFrom now on we will use g++!

Page 2: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Example (revisited)

Goal:

• Graphics package

• Handle drawing of different shapes

• Maintain list of shapes

Page 3: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Solution #1

class Shape {public:

enum Type { e_square, e_circle, e_triangle };Shape( Type t, Point center, double width, double height);void draw();double area();…

private:Type m_type;Point m_center;…

};

Page 4: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Solution #1

• This solution gives a nice “wrapping” to the solution we consider in C. (switch command)

Pros:• Simple, directCons:• Adding new shapes requires changing all

procedures that deal with shape.• Require fat interface in order to support all kinds

of shapes.• No type checking. Unsafe!

Page 5: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Solution #2 – different classes

class Square {

public:

void draw();

double area();

};

class Circle {

public:

void draw();

double area();

};

Page 6: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Solution #3 - Inheritanceclass 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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Inheritance & Overloading

• Derived inherits the method foo() from Base. – The inherited class is using methods of the

base class

• Derived overloads the implementation of bar().– This mechanism allows an inherited class to

specialize the implementation.

Page 12: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Static resolution 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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Dynamic Resolution

• This is clearly not what we want to do in this example.

• A more desirable here solution,

Dynamic resolution (Polymorphism):

• Based on the type of the object.

• Determined at run time.

[Java Like!]

Page 15: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Dynamic Resolution Cont

• 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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Solution #4: dynamic resolution

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

• See Shapes- virtual.cpp

Page 17: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Virtual Destructor

• Destructor is like any other method

• The example uses static resolution, and hence not the intended 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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Polymorphism & Inheritance

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

Points of care:

• Choice of virtual methods.– Run time considerations efficiency.

• Use of virtual destructor for base class!

Page 27: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Shapes & Sizes

Revisiting our example, we writeclass Shape {public:

…virtual ~Shape(); // virtual destructor

virtual void draw(); // virtual methodvirtual double area(); // also…

};

How do we implement Shape::draw() ?

Page 28: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Inheritance & Abstract Classes

• In this example, we never want to deal with objects of type Shape– Shape serves the role of an interface

• 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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Abstract Classes

• We can specify that Shape::draw() does not exist

class Shape {public:…virtual ~Shape(); // virtual destructor

virtual void draw() = 0; // pure virtualvirtual double area() = 0; // Also…

};

Page 30: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Abstract Classes

• 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: Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.

Virtual Methods - Tips

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

• Never call virtual methods during construction and destruction! (invalid object state)

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

• Use pure abstract classes to define interfaces.• Use inheritance with care: Be sure that this is

the appropriate solution.