Advanced Program Design with C++

33
Concordia University Department of Computer Science and Software Engineering ADVANCED PROGRAM DESIGN WITH C++ Polymorphism Virtual functions Abstract classes Slicing problem Value and reference semantics Joey Paquet, 2007- 2014 1 COMP 345 - Advanced Program Design with C++ Function pointers Virtual functions tables Diamond problem Virtual inheritance

description

Advanced Program Design with C++. Polymorphism Virtual functions Abstract classes Slicing problem Value and reference semantics. Function pointers Virtual functions tables Diamond problem Virtual inheritance. Polymorphism. Polymorphism Associating many meanings to one function. - PowerPoint PPT Presentation

Transcript of Advanced Program Design with C++

Page 1: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

ADVANCED PROGRAM DESIGN WITH C++Polymorphism Virtual functionsAbstract classes Slicing problemValue and reference semantics

Joey Paquet, 2007-2014

1COMP 345 - Advanced Program Design with C++

Function pointersVirtual functions tablesDiamond problemVirtual inheritance

Page 2: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• 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.

Polymorphism

Joey Paquet, 2007-2014

2COMP 345 - Advanced Program Design with C++

Page 3: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• 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

Polymorphism

Joey Paquet, 2007-2014

3COMP 345 - Advanced Program Design with C++

Page 4: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• Each class needs a different getArea() function• Can define a member getArea() in each class, so:

• Nothing new here yet…

Polymorphism

Joey Paquet, 2007-2014

4COMP 345 - Advanced Program Design with C++

Page 5: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• Problem!• Parent class CShape 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

Polymorphism

Joey Paquet, 2007-2014

5COMP 345 - Advanced Program Design with C++

Page 6: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• 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 print() to use the functionTriangle::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() function 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.

Polymorphism

Joey Paquet, 2007-2014

6COMP 345 - Advanced Program Design with C++

Page 7: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Polymorphism

Joey Paquet, 2007-2014

7COMP 345 - Advanced Program Design with C++

Page 8: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Virtual methods

Joey Paquet, 2007-2014

8COMP 345 - Advanced Program Design with C++

Page 9: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• 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”.

Polymorphism: virtual methods

Joey Paquet, 2007-2014

9COMP 345 - Advanced Program Design with C++

Page 10: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• 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.

Polymorphism: virtual methods

Joey Paquet, 2007-2014

10COMP 345 - Advanced Program Design with C++

Page 11: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Polymorphism: virtual methods

Joey Paquet, 2007-2014

11COMP 345 - Advanced Program Design with C++

Page 12: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• 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.

Polymorphism: virtual destructors

Joey Paquet, 2007-2014

12COMP 345 - Advanced Program Design with C++

• 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.

Page 13: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Pure virtual functionsAbstract classes

Joey Paquet, 2007-2014

13COMP 345 - Advanced Program Design with C++

Page 14: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• 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.

Polymorphism: pure virtual methods and abstract classes

Joey Paquet, 2007-2014

14COMP 345 - Advanced Program Design with C++

Page 15: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• There are two main uses for pure virtual functions/abstract classes: 1. Classes that are to be used polymorphically with different

subclass behaviors.2. Interfaces, i.e. classes that contain only pure virtual

functions. This is equivalent to Java’s interfaces.

• Contrary to Java interfaces, C++ abstract classes can provide a definition for some of their methods, and can have non-constant data members.

Polymorphism: pure virtual methods and abstract classes

Joey Paquet, 2007-2014

15COMP 345 - Advanced Program Design with C++

Page 16: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Object slicing: value semantics and reference semantics

Joey Paquet, 2007-2014

16COMP 345 - Advanced Program Design with C++

Page 17: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Object slicing

Joey Paquet, 2007-2014

17COMP 345 - Advanced Program Design with C++

Page 18: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• Anything that is a Dog is also a Pet:

• Can assign values to parent-types, but not inversely• A Pet is not necessarily a Dog

• However, the values assigned to vpet1 and vpet2 lose their breed field• Called the slicing problem

• This is due to the fact that value semantics was used in the operations to assign/copy the object in the operation. The resulting copy is a Pet that has lost its identity as a Dog. • When using pointers or references, reference semantics is used, which does not result in slicing and enables polymorphism.

Object slicing

Joey Paquet, 2007-2014

18COMP 345 - Advanced Program Design with C++

Page 19: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Value semantics: object slicing

Joey Paquet, 2007-2014

19COMP 345 - Advanced Program Design with C++

Page 20: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Reference semantics: polymorphism

Joey Paquet, 2007-2014

20COMP 345 - Advanced Program Design with C++

Page 21: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Function pointers

Joey Paquet, 2007-2014

21COMP 345 - Advanced Program Design with C++

Page 22: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• Function pointers are pointers, i.e. variables, which point to the starting address of a function’s code. • Enables the call to different functions, depending on the function pointer value, which can be pointing to different functions’ code in time. • In C++, a function pointer can only point to different functions with the same signature (single dispatch mechanism). Single dispatch assumes that the same number/types of values are passed/returned during a function call. • multiple dispatch – dispatch to any function (independent of signature), with a an elaborated mechanism for mapping parameters/return value.

Function pointers

Joey Paquet, 2007-2014

22COMP 345 - Advanced Program Design with C++

Page 23: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Function pointers

Joey Paquet, 2007-2014

23COMP 345 - Advanced Program Design with C++

Page 24: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Virtual function tables

Joey Paquet, 2007-2014

24COMP 345 - Advanced Program Design with C++

Page 25: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• C++ implements virtual functions through a form of late binding using virtual function tables, also known as virtual method tables, or vtables. • Every class that includes or inherits at least one virtual function

is assigned a virtual function table.• A vtable is a static array of function pointers. • There is one function pointer for each virtual function declared or

inherited in the class. • Each pointer points to the function belonging to the most derived

class that implements this function. • For pure virtual functions, one can assume that the vtable

contains a NULL pointer. Some implementations implement a pointer to a special function that may throw an exception upon call.

• Every object created that belongs to a class hierarchy having virtual functions keeps its own vtable that is used to resolve its function calls at run time.

• When this object is assigned to a variable of one of its supertypes, its own vtable is used to resolve the function calls.

Polymorphism: virtual function tables

Joey Paquet, 2007-2014

25COMP 345 - Advanced Program Design with C++

Page 26: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Polymorphism: virtual function tables

Joey Paquet, 2007-2014

26COMP 345 - Advanced Program Design with C++

Base* __vptr

virtual function1() virtual function2()

Base vtablefunction1()function2()

Derived1: Base* __vptr

virtual function1() virtual function5()

Derived1 vtablefunction1()function2()

Derived2: Base* __vptr

virtual function2() virtual function3()

virtual function3() v = 0 function4()

function3()

function3()

function6() function5()

function4() virtual function5()

Derived2 vtablefunction1()function2() function3() function5()

Derived3: Derived1* __vptr

virtual function3() Derived3 vtable

function1()function2() function3() function5()

Page 27: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Polymorphism: virtual function tables

Joey Paquet, 2007-2014

27COMP 345 - Advanced Program Design with C++

Page 28: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Virtual inheritance and the diamond problem

Joey Paquet, 2007-2014

28COMP 345 - Advanced Program Design with C++

Page 29: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• Multiple inheritance allows you to use more than once the same abstract class in a class hierarchy, similarly to Java’s Interfaces.

• Here, IComm is an abstract class having only pure virtual methods and no data members and will not be instantiated.

• You may also want to use the same non-abstract class more than once in a hierarchy.

• Here, Recorder is a class that is used to record all the communications emitted or received. There is one store for emission, and another store for reception.

Multiple use of a class in a hierarchy

Joey Paquet, 2007-2014

29COMP 345 - Advanced Program Design with C++

IComm IComm

Transmitter Receiver

WalkieTalkie

Recorder Recorder

Transmitter Receiver

WalkieTalkie

Page 30: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• But what if what you really want is a single Store that records all received/emitted messages?

• In C++, if you set both Transmitter and Receiver to inherit from Recorder, both of them will by default have their own copy of a different Recorder object in memory.

• This is going to also lead to ambiguities when, e.g. a WalkieTalkie object refers to a member of Recorder. As there are in fact two separate stores.

• This is called the diamond problem.

• In order to solve both of these problems, C++ offers what is called virtual inheritance.

Diamond problem

Joey Paquet, 2007-2014

30COMP 345 - Advanced Program Design with C++

Recorder

Transmitter Receiver

WalkieTalkie

Page 31: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• To signify virtual inheritance, the classes that are to share a same instance of a class in a hierarchy have to use the virtual keyword in their inheritance specification.

• This changes how the objects of the most derived class are created, and how their constructors call each other implicitly or explicitly.

• The class responsible to call the constructor on the virtually inherited class is the first derived class that includes all instances of a virtually inherited class.

• In the example here, it is the class D.

• Any other call to a constructor of a virtually inherited class up the hierarchy is ignored.

Virtual inheritance

Joey Paquet, 2007-2014

31COMP 345 - Advanced Program Design with C++

Page 32: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

Virtual inheritance

Joey Paquet, 2007-2014

32COMP 345 - Advanced Program Design with C++

Page 33: Advanced Program Design with C++

Concordia University

Department of Computer Science and Software Engineering

• Mark Radford. C++ Interface Classes - An Introduction. Overload Journal #62 - Aug 2004.

• LearnCPP.com The virtual table. • Andrei Milea. Solving the Diamond Problem with Virtual

Inheritance. Cprogramming.com. • Walter Savitch. Polymorphic and Virtual Functions in C++.

Informit, Pearson. March 2002. • Robert C. Martin. Java and C++, A critical comparison. March

1997. • Andrzej's C++ blog. Value semantics. February 2013.

References

Joey Paquet, 2007-2014

33COMP 345 - Advanced Program Design with C++