Download presentation
Presentation is loading. Please wait.
1
Advanced Program Design with C++
COMP Advanced Program Design with C++ Advanced Program Design with C++ Virtual functions Abstract classes Slicing problem Function pointers Polymorphism Virtual functions tables Joey Paquet,
2
Polymorphism Virtual Polymorphism
COMP Advanced Program Design with C++ Polymorphism Polymorphism Associating many meanings to one function. Virtual functions provide this capability. Fundamental principle of object-oriented programming. Virtual Existing in "essence" though not in fact. Virtual functions. Virtual (abstract) classes. Joey Paquet,
3
Best explained by example: Classes for several kinds of figures
COMP Advanced Program Design with C++ Polymorphism Best explained by example: Classes for several kinds of figures Rectangles, circles, etc. Each figure is an object of a different class Each have different data elements and formulas to compute them Rectangle data: name, area, perimeter, height, width Circle data: name, area, perimeter, radius All derive from one parent-class: CShape Requires a method getArea() Different formula to compute different figures’ area, requires different implementation for each kind of figure Joey Paquet,
4
Each class needs a different getArea() function
COMP Advanced Program Design with C++ Polymorphism Each class needs a different getArea() function Can define a member getArea() in each class, so: Nothing new here yet… CRectangle r; CCircle c; r.getArea(); //Calls Rectangle’s getArea c.getArea(); //Calls Circle’s getArea Joey Paquet,
5
COMP 345 - Advanced Program Design with C++
Polymorphism Problem! Parent class Figure may contain functions that applies to all kinds of figures. Consider: print() : prints out all characteristics common to all kinds of figures Fine for getName(), as it has common behavior. However, getArea()has subclass-specific behavior Complications! Which getArea() function to call? From which class? Here, a function that exposes common behavior uses another function that exposes subclass-specific behavior. May hardcode a function that calls the right getArea() depending on which subclass the figure in question is. Need a mechanism to call subclass-specific behavior automatically Joey Paquet,
6
COMP 345 - Advanced Program Design with C++
Polymorphism Problem! Consider a new kind of figure later coming along: CTriangle class derived from CShape class Function print() inherited from CShape Will it work for triangles? It uses getArea(), which is different for each subclass of figure It will use CShape::getArea(), which was not made to work for triangles We want the inherited function center() to use the function Triangle::getArea() and not the function CShape::getArea() But class CTriangle wasn’t even written when CShape::print() was written. It does not “know” about triangles. If print() is hard-coded to call the right getArea() depending on the type of CShape, we need to change the implementation of print()every time we add a new subclass of Cshape. Again, we need a mechanism to automatically call subtype-specific behavior. Joey Paquet,
7
Polymorphism void displayCShapeDynamicCastDemo(CShape& shape) {
COMP Advanced Program Design with C++ Polymorphism void displayCShapeDynamicCastDemo(CShape& shape) { CShape* p = &shape; CCircle* p1 = dynamic_cast<CCircle*>(p); CRectangle* p2 = dynamic_cast<CRectangle*>(p); CTriangle* p3 = dynamic_cast<CTriangle*>(p); if (p1 != NULL){ cout << "Circle's area is " << p1->getArea() << endl; cout << "Circle's radius is " << p1->getRadius() << endl; } if (p2 != NULL){ cout << "Rectangle's area is " << p2->getArea() << endl; cout << "Rectangle's width is " << p2->getWidth() << endl; cout << "Rectangle's height is " << p2->getLength() << endl; if (p3 != NULL){ cout << "Triangle's area is " << p3->getArea() << endl; cout << "Triangle's width is " << p3->getHeight() << endl; cout << "Triangle's height is " << p3->getBase() << endl; Joey Paquet,
8
Polymorphism: virtual methods
COMP Advanced Program Design with C++ Polymorphism: virtual methods Virtual methods allow to declare such a subtype-specific behavior. If an object of type CShape is declared and instantiated with an object of type e.g. CRectangle, calling any of its virtual methods will result in using CRectangle’s behavior, even though its type is declared as CShape. This requires a dynamic run-time binding mechanism. In C++ implementation, it is called “dynamic binding” or “late binding”. class CShape{ protected: double area; string name; public: CShape() : name("anonymous"){ } CShape(string newName) : name(newName){ string getName(){ return name; virtual double getArea()= 0; virtual void print(){ cout << "Shape:" << name << endl; cout << "Area: " << getArea() << endl; }; bool operator < (CShape &s1, CShape &s2){ return (s1.getArea() < s2.getArea()); Joey Paquet,
9
Polymorphism: virtual methods
COMP Advanced Program Design with C++ Polymorphism: virtual methods Polymorphic behavior comes when you declare an object of a base class type and then instantiate it with an instance of a derived type. In this case, the type of the object can only be determined dynamically at run-time. If a method is declared as virtual, its subtype behavior is branched upon. If a method is not declared as virtual, the base type behavior is branched upon. void main() { CRectangle *shapeRect = new CRectangle("shapeRect", 16.8, 8.8); CCircle *shapeCircle = new CCircle("shapeCircle", 13.8); CTriangle *shapeTriangle = new CTriangle("shapeTriangle", 2.5, 3.8); CShape *shapes[] = { shapeRect, shapeCircle, shapeTriangle }; for (int i = 0; i < sizeof(shapes) / sizeof(shapes[0]); i++){ shapes[i]->getArea(); shapes[i]->print(); if (i>0) cout << "Shape[" << i << "] area (" << shapes[i]->getArea() << ") less than Shape[" << i - 1 << "] area (" << shapes[i-1]->getArea() << ") : " << (*shapes[i] < *shapes[i-1]) << endl; } delete shapeRect; delete shapeCircle; delete shapeTriangle; Joey Paquet,
10
Virtual methods COMP 345 - Advanced Program Design with C++
class CCircle : public CShape{ double radius; public: CCircle() : CShape(), radius(1){ }; CCircle(string n, double r) : CShape(n), radius(r) { void setRadius(double r) { radius = r; } double getRadius() const { return radius; } double getArea(){ area = * radius * radius; return area; } void print(){ CShape::print(); cout << "Circle:" << endl; cout << "Radius: " << radius << endl; class CRectangle : public CShape{ double length; double width; public: CRectangle() : CShape(), length(1), width(1){ } CRectangle(string n, double l, double w) : CShape(n), length(l), width(w){ void setLength(double l) { length = l; } void setWidth(double w) { width = w; } double getLength() const { return length; } double getWidth() const { return width; } double getArea(){ area = length * width; return area; void print(){ CShape::print(); cout << "Rectangle:" << endl; cout << "Height: " << length << " Width: " << width << endl; }; Joey Paquet,
11
Polymorphism: pure virtual methods and abstract classes
COMP Advanced Program Design with C++ Polymorphism: pure virtual methods and abstract classes In C++, some virtual methods can be declared as “pure virtual”. Any class with at least one pure virtual method is an abstract class. No instance of an abstract class can be created. However, an abstract class still represents a data type. To be used, abstract classes need to be derived by subclasses that provide an implementation to all their pure virtual methods. A class that derives an abstract class and does not provide an implementation for all the pure virtual functions it inherits is itself still an abstract class. Contrary to Java interfaces, C++ abstract classes can provide a definition for some of their methods, and can have non-constant data members. Joey Paquet,
12
Polymorphism: pure virtual methods and abstract classes
COMP Advanced Program Design with C++ Polymorphism: pure virtual methods and abstract classes There are two main uses for pure virtual functions/abstract classes: Classes that are to be used polymorphically with different subclass behaviors. Interfaces, i.e. classes that contain only pure virtual functions. This is equivalent to Java’s interfaces. class CShape{ protected: double area; string name; public: CShape() : name("anonymous"){ } CShape(string newName) : name(newName){ string getName(){ return name; virtual double getArea()= 0; virtual void print(){ cout << "Shape:" << name << endl; cout << "Area: " << getArea() << endl; }; class Iserialisable { public: virtual void load(istream& in) = 0; virtual void save(ostream& out) = 0; virtual ~serialisable(); } Joey Paquet,
13
COMP 345 - Advanced Program Design with C++
Virtual destructors If you implement a class to be used polymorphically, you probably need to declare its destructor as virtual. If an object of a derived class is assigned to a pointer to a base class, and then later deleted using the base class pointer, the base class destructor will be used to delete the object. The derived class’ destructor will thus never be called, possibly leading to a resource leak. Rule of thumb: always declare the destructor as virtual if a class is to be use polymorphically. class Base { public: virtual ~Base(){ cout << "Base::~Base()" << endl; } }; class Derived : public Base { ~Derived(){ cout << "Derived::~Derived()" << endl; int main(){ Base *b = new Derived(); delete b; int i; cin >> i; Joey Paquet,
14
COMP 345 - Advanced Program Design with C++
References Mark Radford. C++ Interface Classes - An Introduction. Overload Journal #62 - Aug 2004. Joey Paquet,
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.