Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Data Structures - CSCI 102 CS102 C++ Polymorphism Prof Tejada.

Similar presentations


Presentation on theme: "1 Data Structures - CSCI 102 CS102 C++ Polymorphism Prof Tejada."— Presentation transcript:

1 1 Data Structures - CSCI 102 CS102 C++ Polymorphism Prof Tejada

2 3 Data Structures - CSCI 102 Polymorphism What is polymorphism? The ability of an object of one type to appear and be used like an object of a different type Remember our Shape and Triangle classes? Based on inheritance, Triange Is-A Shape so... We can actually pass Triangles around as Shapes! Triangle t(5,5,15,20); Shape tval = t; Shape &tref = t; Shape *tptr = &t; Shape *tptr2 = new Triangle(1,2,55,62); You can write very advanced code with polymorphism Write algorithms & frameworks that manipulate base class Can even write code for subclasses that hasn’t been realized or designed!

3 So what does this code do? 4 Data Structures - CSCI 102 Polymorphism Triangle t(5,5,15,20); t.print(); Shape tval = t; tval.print(); Shape &tref = t; tref.print(); Shape *tptr = &t; tptr->print(); It should call the Triangle object’s overloaded print method, right? Does it?

4 Even though we can pass around a Triangle as a Shape, it doesn’t help if we can’t make it call Triangle’s overloaded methods 5 Data Structures - CSCI 102 Early/Static/Compile-Time Binding When your code is compiled, the compiler directly associates a function call with a memory location to make function calls a fast lookup Why does this happen? Isn’t there some way to tell the compiler to wait until run-time to figure out what version of the "print()" function it should call? When you compiler sees "s.print()", it immediately associates it with the Shape class

5 6 space) Data Structures - CSCI 102 Virtual Functions Tells the C++ to wait until the code runs to figure out what version of a method it should actually call The keyword virtual tells C++ to find the "most-derived" version of a method (a.k.a. the one farthest down the inheritance tree that’s still relevant) How is it used? Just add the keyword virtual to the beginning of any function prototype in your class Technically, you only have to add virtual to the superclass method, but it’s good style if you add it to all of the functions that are affected by it Why not just declare every function virtual? It’s more expensive than normal lookup (time &

6 Before we had this: 7 Data Structures - CSCI 102 Virtual Functions Now we have this instead: class Shape {... void print() const; }; class Shape {... virtual void print() const; };

7 It tells C++ that it’s not possible to know what version of that particular function to call until run-time How does the virtual keyword actually work? 8 Data Structures - CSCI 102 Late/Dynamic/Run-Time Binding The compiler constructs a virtual table for every class that has a virtual function Each of these classes stores a hidden pointer to its own virtual table The virtual table provides a run-time lookup for each class to know what version of functions to call using function pointers

8 If you don’t C++ will only call the superclass destructor and will skip your subclass destructor If you’re using inheritance, you should ALWAYS make your base class’ Destructor virtual 9 Data Structures - CSCI 102 Other "Virtual" Details Dynamic binding only works for references and pointers!!! Triangle t(5,5,15,20); t.print(); Shape tval = t; tval.print(); //calls Shape’s print()!!! Shape &tref = t; tref.print(); //calls Triangle’s print() Shape *tptr = &t; tptr->print(); //calls Triangle’s print()

9 Allows you to reuse a lot of code that works for similar objects Why is polymorphism useful? 10 Data Structures - CSCI 102 Polymorphism Allows you to add new classes to your inheritance hierarchy, but all your existing methods will still work just fine! Allows you to construct very sophisticated code that is simple, but powerful What if we add a new subclass of "Shape"?

10 What if there’s a function that the superclass can’t define, but we need the subclasses to define? 11 Data Structures - CSCI 102 Pure Virtual Functions class Shape { virtual double getArea() const; }; The problem here is that Shape has no details about how to calculate an area. Our function would end up looking something like this (not very useful): double Shape::getArea() const { return 0; }

11 The getArea() function is not meaningful for Shape, but it is meaningful for all subclasses of Shape 12 Data Structures - CSCI 102 Pure Virtual Functions Need to make getArea() as a pure virtual function Shape does not need to implement getArea() All subclasses of shape should be forced to implement a definition of getArea() class Shape { virtual double getArea() const = 0; };

12 If Shape contains a pure virtual function, it can no longer be instantiated! What would happen if you made a Shape object and tried to call getArea()? What are the consequences of making a function in a class a pure virtual function? 13 Data Structures - CSCI 102 Abstract Base Classes Shape becomes an abstract base class Any subclass of Shape that doesn’t implement a real version of getArea() also becomes an abstract base class! If you want to use your derived classes, you MUST override the getArea() method

13 Here is an example of a function that is implemented using polymorphism to maintain flexibility: 14 Data Structures - CSCI 102 Polymorphic Print Function void printArea(const Shape& s) { cout << "Area = " << s.getArea() << endl; } What if we decide to add another subclass like Rectangle to our existing inheritance hierarchy? You won’t need to change printArea()!

14 Using the ideas of pure virtual functions and abstract base classes you could create a class that has no implementation at all! 15 Data Structures - CSCI 102 Interface Classes Very useful for when you want to tell subclasses what functions they must provide, but you don’t want to influence their implementation e.g. "Shape" would become "IShape" An interface class is a class that contains only pure virtual functions It’s a better/safer way to do multiple inheritance (Java and C# actually split interface out) Interface classes usually prefix their name with I Actually, it is THE right way to do multiple inheritance

15 17 Data Structures - CSCI 102 polymorph_point.h #ifndef POLYMORPH_POINT_H_ #define POLYMORPH_POINT_H_ #include class Point { private: int x; int y; public: Point(int newx,int newy) : x(newx), y(newy) { } virtual ~Point() { } //A virtual destructor int getX() const { return int getY() const { return void setX(int newx) { x = void setY(int newy) { y = x; } y; } newx; } newy; } friend std::ostream& operator<<(std::ostream& out, const Point& b); }; std::ostream& operator<<(std::ostream& out, const Point& b) { out << "(" << b.x << "," << b.y << ")"; return out; } #endif /* POLYMORPH_POINT_H_ */

16 18 Data Structures - CSCI 102 polymorph_shape.h #ifndef POLYMORPH_SHAPE_H_ #define POLYMORPH_SHAPE_H_ #include "polymorph_point.h" class Shape { protected: Point center; public: Shape(int x,int y) : center(x,y) { } //A virtual destructor virtual ~Shape() { } Point getCenter() const { return center; } void setCenter(Point p) { center = p; } //A virtual print function virtual void print() const { std::cout << "Shape located at " << center << std::endl; } //A pure virtual area calculation function virtual double getArea() const = 0; }; #endif /* POLYMORPH_SHAPE_H_ */

17 19 Data Structures - CSCI 102 polymorph_triangle.h #ifndef POLYMORPH_TRIANGLE_H_ #define POLYMORPH_TRIANGLE_H_ #include "polymorph_point.h" #include "polymorph_shape.h" class Triangle : public Shape { private: int base; int height; public: Triangle(int b, int h, int x, int y) : Shape(x,y) { base = b; height = h; } int getBase() const { int getHeight() const void setBase(int b) { void setHeight(int h) return base; } { return height; } base = b; } { height = h; } virtual void print() const { std::cout << "Triangle located at " << center << std::endl; } virtual double getArea() const { return(.5*base*height); } }; #endif /* POLYMORPH_TRIANGLE_H_ */

18 20 Data Structures - CSCI 102 polymorph_rectangle.h #ifndef POLYMORPH_RECTANGLE_H_ #define POLYMORPH_RECTANGLE_H_ #include "polymorph_point.h" #include "polymorph_shape.h" class Rectangle : public Shape { private: int width; int height; public: Rectangle(int w, int h, int x, int y) : Shape(x,y) { width = w; height = h; } int getWidth() const { return width; } int getHeight() const { return height; } void setBase(int w) { width = w; } void setHeight(int h) { height = h; } virtual void print() const { std::cout << "Rectangle located at " << center << std::endl; } virtual double getArea() const { return(width*height); } }; #endif /* POLYMORPH_RECTANGLE_H_ */

19 Data Structures - CSCI 102 polymorph_main.cpp #include "polymorph_point.h" "polymorph_shape.h" "polymorph_triangle.h" "polymorph_rectangle.h" using namespace std; void printArea(const Shape& s) { cout << "Area of shape is " << s.getArea() << endl; } int main() { Triangle* t = new Triangle(10,10,10,10); printArea(*t); delete t; Rectangle* r = new Rectangle(10,15,20,25); printArea(*r); delete r; } 22


Download ppt "1 Data Structures - CSCI 102 CS102 C++ Polymorphism Prof Tejada."

Similar presentations


Ads by Google