void Transaction::print() { cout << "Name: " << name << " Amount: " << amount << endl; }

Similar documents
Inheritance, and Polymorphism.

CS250 Intro to CS II. Spring CS250 - Intro to CS II 1

Polymorphism Part 1 1

What is Polymorphism? Quotes from Deitel & Deitel s. Why polymorphism? How? How? Polymorphism Part 1

CS11 Introduction to C++ Fall Lecture 7

VIRTUAL FUNCTIONS Chapter 10

Chapter Four: Loops II

Data Structures and Other Objects Using C++

POLYMORPHISM 2 PART. Shared Interface. Discussions. Abstract Base Classes. Abstract Base Classes and Pure Virtual Methods EXAMPLE

POLYMORPHISM 2 PART Abstract Classes Static and Dynamic Casting Common Programming Errors

POLYMORPHISM Polymorphism: the type Polymorphism taking many shapes type of object

CS 251 Intermediate Programming Inheritance

15: Polymorphism & Virtual Functions

CS Lecture #6. Administrative... Assignment #2 Graded NN Turned In, Average Grade: XX Assignment #3 due on Thursday

Solving a 2D Maze. const int WIDTH = 10; const int HEIGHT = 10;

Unit 7. 'while' Loops

Polymorphism. Zimmer CSCI 330

Fast Introduction to Object Oriented Programming and C++

Function Overloading

QUIZ. Write the following for the class Bar: Default constructor Constructor Copy-constructor Overloaded assignment oper. Is a destructor needed?

Programming Language Concepts Object-Oriented Programming. Janyl Jumadinova 28 February, 2017

CS Lecture #14

Super-Classes and sub-classes

CS32 - Week 4. Umut Oztok. Jul 15, Umut Oztok CS32 - Week 4

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

CSCI 104 Polymorphism. Mark Redekopp David Kempe

Chapter Four: Loops. Slides by Evan Gallagher. C++ for Everyone by Cay Horstmann Copyright 2012 by John Wiley & Sons. All rights reserved

CS 162, Lecture 25: Exam II Review. 30 May 2018

Polymorphism CSCI 201 Principles of Software Development

COMP322 - Introduction to C++

OOP THROUGH C++(R16) int *x; float *f; char *c;

UNIVERSITI TEKNIKAL MALAYSIA MELAKA FACULTY INFORMATION TECHNOLOGY AND COMMUNICATION (FTMK) BITE 1513 GAME PROGRAMMING I.

C++ Important Questions with Answers

CIS 190: C/C++ Programming. Lecture 11 Polymorphism

OOPS Viva Questions. Object is termed as an instance of a class, and it has its own state, behavior and identity.

COMP322 - Introduction to C++ Lecture 09 - Inheritance continued

Note 12/1/ Review of Inheritance Practice: Please write down 10 most important facts you know about inheritance...

Instantiation of Template class

int n = 10; int sum = 10; while (n > 1) { sum = sum + n; n--; } cout << "The sum of the integers 1 to 10 is " << sum << endl;

Before we start - Announcements: There will be a LAB TONIGHT from 5:30 6:30 in CAMP 172. In compensation, no class on Friday, Jan. 31.

Polymorphism 8. Polymorphism. Content. Normal Member Functions Accessed with Pointers. Polymorphism. Virtual Members Abstract Class

Arrays in C++ Instructor: Andy Abreu

Object Oriented Programming: Inheritance Polymorphism

Inheritance. Overview. Chapter 15 & additional topics. Inheritance Introduction. Three different kinds of inheritance

Overriding המחלקה למדעי המחשב עזאם מרעי אוניברסיטת בן-גוריון

CS Exam 2 Study Suggestions

1: Introduction to Object (1)

Data Structures (INE2011)

Operator overloading

Last class. -More on polymorphism -super -Introduction to interfaces

CS-202 Introduction to Object Oriented Programming

Inheritance, Polymorphism, and Interfaces

OOP Fundamental Concepts

(12-1) OOP: Polymorphism in C++ D & D Chapter 12. Instructor - Andrew S. O Fallon CptS 122 (April 3, 2019) Washington State University

Object-oriented features

The name of our class will be Yo. Type that in where it says Class Name. Don t hit the OK button yet.

Coding Workshop. Learning to Program with an Arduino. Lecture Notes. Programming Introduction Values Assignment Arithmetic.

Software Design and Analysis for Engineers

Introduction to C++ Introduction to C++ Dr Alex Martin 2013 Slide 1

Programming in C++: Assignment Week 6

Lecture 3. COMP1006/1406 (the Java course) Summer M. Jason Hinek Carleton University

ENGI 1020 Introduction to Computer Programming J U L Y 5, R E Z A S H A H I D I

Increases Program Structure which results in greater reliability. Polymorphism

Lecture 11. Demonstration #1. More Inheritance, More Constructors. Absolute C++ Chapter 15. Virtual Functions. Overriding

CS 103 Lab - Party Like A Char Star

static CS106L Spring 2009 Handout #21 May 12, 2009 Introduction

CSC207 Week 3. Larry Zhang

Java Object Oriented Design. CSC207 Fall 2014

CS107 Handout 37 Spring 2007 May 25, 2007 Introduction to Inheritance

#include <iostream> #include <algorithm> #include <cmath> using namespace std; int f1(int x, int y) { return (double)(x/y); }

Control Structures. Code can be purely arithmetic assignments. At some point we will need some kind of control or decision making process to occur

Inheritance. OOP components. Another Example. Is a Vs Has a. Virtual Destructor rule. Virtual Functions 4/13/2017

Advanced Programming - JAVA Lecture 4 OOP Concepts in JAVA PART II

Course "Data Processing" Name: Master-1: Nuclear Energy Session /2018 Examen - Part A Page 1

Programming Exercise 14: Inheritance and Polymorphism

do { statements } while (condition);

Inheritance. Chapter 15 & additional topics

CS 216 Fall 2007 Midterm 1 Page 1 of 10 Name: ID:

Relationships Between Real Things CSE 143. Common Relationship Patterns. Employee. Supervisor

COMP 250 Fall inheritance Nov. 17, 2017

C++ Crash Kurs. Polymorphism. Dr. Dennis Pfisterer Institut für Telematik, Universität zu Lübeck

The 10 Minute Guide to Object Oriented Programming

CPSC 427: Object-Oriented Programming

Inheritance. Chapter 15 & additional topics

Implementing an ADT with a Class

OVERRIDING. 7/11/2015 Budditha Hettige 82

Chapter 1 Getting Started

Relationships Between Real Things. CSE 143 Java. Common Relationship Patterns. Composition: "has a" CSE143 Sp Student.

QUIZ. How could we disable the automatic creation of copyconstructors

Review: Object Diagrams for Inheritance. Type Conformance. Inheritance Structures. Car. Vehicle. Truck. Vehicle. conforms to Object

Casting and polymorphism Enumeration

Object-Oriented Concept

C How to Program, 6/e by Pearson Education, Inc. All Rights Reserved.

Pointers, Arrays and Parameters

C++ Data Types. 1 Simple C++ Data Types 2. 3 Numeric Types Integers (whole numbers) Decimal Numbers... 5

Scientific Computing

Lecture 5: Inheritance

Relationships Between Real Things CSC 143. Common Relationship Patterns. Composition: "has a" CSC Employee. Supervisor

What are the characteristics of Object Oriented programming language?

These are notes for the third lecture; if statements and loops.

Transcription:

Polymorphism Polymorphism literally means many shapes. Inheritance allows you to define a base class and derive classes from the base class. Polymorphism allows you to make changes in the method definition for the derived classes and have those changes apply to the methods written in the base class. In C++ you must specify a method as virtual if you want this to happen. Consider the Transaction and CreditCardTransaction classes that we wrote in the last lecture. In this case, CreditCardTransaction is derived from Transaction. void Transaction::print() cout << "Name: " << name << " Amount: " << amount << endl; void CreditCardTransaction::print() Transaction::print(); // Call parent print function cout << "Number: " << number << endl; // Add number If we create a Transaction object then we get what you might expect: Transaction t("bilbo", 199.59); t.print(); // Outputs Name: Bilbo Amount: 199.59 If we create a CreditCardTransaction object then we also get what you might expect: CreditCardTransaction cct("frodo", "1111 0000", 10.25); cct.print(); // Outputs Name: Frodo Amount: 10.25 // Number: 1111 0000 But what if we create a CreditCardTransaction, copy (or typecast) it to a Transaction, and call print? You might wonder why you would want to do this, but such a circumstance is actually quite common. For example: CreditCardTransaction cct("frodo", "1111 0000", 10.25); Transaction *t = &cct; t->print(); First, why is this legal? It is because a CreditCardTransaction Is A Transaction. This makes it legal to assign the more specific object to the more general one. But we can t go the other way we can t assigned a Transaction object to a CreditCardTransaction, because the Transaction might be something like a CashTransaction and it s not valid to make it a CreditCardTransaction. So what is the output? We have two possible choices since there are two print functions. Since we originally created cct as a CreditCardTransaction it makes some

sense to use CreditCardTransaction s print function. On the other hand, since we are invoking it as a Transaction object, it also makes sense to use Transaction s print function. The answer is: Frodo Amount: 10.25 In other words, it uses the print function defined for Transaction. This might be surprising to you if you learned Java first, because in Java you d get the credit card number. So the bottom line, is when we redefine a function in C++, the function that is invoked is determined by the type of the object that does the invoking. We start at the class based on the type of the calling object, if the function is defined there then we use it, otherwise C++ searches up the inheritance hierarchy and invokes the first function hat is found that matches the name (i.e. the inheritance part). Unfortunately, the behavior we just saw is not what we normally want. Usually we want to call the function that was defined for the class of the object when it was originally created! Here is an example. Let s say that we have an array of transactions that represent all of the transactions that happened in one day. There could be many different kinds of transactions, some CreditCardTransactions, some CashTransactions, some CheckTransactions, etc. Transaction* trans[4]; // Array to pointer of Transaction trans[0] = new CreditCardTransaction("Frodo", "0000 0001", 10.50); trans[1] = new CreditCardTransaction("Bilbo", "0000 0000", 99.23); trans[2] = new CashTransaction("Sauron", 10000.50); trans[3] = new CashTransaction("Gandalf", 9510.21); // Output each transaction for (int i = 0; i < 4; i++) trans[i]->print(); cout << endl; // Free memory for (int i = 0; i < 4; i++) delete trans[i]; The problem is this program will only use Transaction::print() and we miss out on the credit card details that we could be printing for Frodo and Bilbo. How to get around this? The solution is to use what are called virtual functions. (This is the default behavior in Java, so you might not be aware that it has a name, since it needs-not-be-named when it always happens in Java).

When we declare a function to be virtual then C++ remembers the type of the object when it was created. If we call a virtual function that exists at multiple levels in the inheritance hierarchy, then C++ uses the function associated with the class of the object when the object was created. To make a function virtual, we just put the keyword virtual in front of the function in the class definition: class Transaction Transaction(void); ~Transaction(void); Transaction(string newname, double newamount); string getname(); double getamount(); virtual void print(); private: double amount; private: string name; ; If we run the same program then now it will output: Name: Frodo Amount: 10.5 Number: 0000 0001 Name: Bilbo Amount: 99.23 Number: 0000 0000 Name: Sauron Amount: 10000.5 Name: Gandalf Amount: 9510.21 Other names for this behavior are: polymorphism, dynamic binding, and late binding. We also say that the function / method print is overridden in the child class. Lots of terminology! At first glance, this might seem like an esoteric feature of C++. However, it s really extremely powerful. One of the amazing things about polymorphism is it lets us invoke functions that might not even exist yet! For example, we could write our code to handle CreditCardTransactions and CashTransactions. One day we decide to handle PayPalTransactions or BitcoinTransactions. We don t have to change any of our existing code! We just write the new classes so they override the print function, and if we add one of these classes to our array then the details will automagically get printed out. We wouldn t even need to recompile the Transaction class. This makes our program really extensible for future functionality.

Pure virtual functions and abstract classes Sometimes it doesn t make sense to define a function at the base class. The prototypical example is to have a Shape class and derived classes like Circle or Square. Consider the following: class Shape virtual int area(); ; class Square : public Shape int area(); int side; ; int Square::area() return side*side; In this case we might want to define area() as a virtual function so we can invoke the function for anything derived from Shape. But the function is going to do totally different things for different kinds of shapes, so it s impossible to define at the Shape class. It must be defined at a derived class. When this situation arises, you can make a pure virtual function. A pure virtual function has no implementation. When you do this in a class then the class becomes an abstract class. Since no implementation exists for a function, you can t make an instance of it. Here is the Shape class turned into an abstract class with a pure virtual function. Just add =0 to the end of the function definition. class Shape virtual int area() = 0; ; One of the side-effects is that any class derived from Shape must implement the area function. The compiler will give an error message if the function is missing. For this reason, abstract classes are sometimes referred to as interfaces. A class has to implement all of the functions defined in the interface.

Polymorphism Example Guessing Game Consider a guessing game where someone is thinking of a number from 0-99 and two other players try to guess the number. The players are told if the guess is too high or too low if they are not correct. Here is the main game code with most of the logic in the playround method: #include <iostream> #include <cstdlib> #include <ctime> #include "Player.h" #include "ComputerPlayer.h" #include "HumanPlayer.h" // Have to pass p1 and p2 by reference to use virtual function static bool playround(player &p1, Player &p2, int number) // Get P1's guess cout << "Player 1: " << p1.getname() << ", it is your turn. "; int p1guess = p1.getguess(); cout << p1.getname() << " guessed " << p1guess << endl; if (p1guess == number) cout << "That is the correct number!" << endl; return false; else if (p1guess < number) cout << "The guess is too low." << endl; else cout << "The guess is too high." << endl; // Get P2's guess cout << "Player 2: " << p2.getname() << ", it is your turn. " << endl; int p2guess = p2.getguess(); cout << p2.getname() << " guessed " << p2guess << endl; cout << "Player 2, " << p2.getname() << ", guessed " << p2guess << endl; if (p2guess == number) cout << "That is the correct number!" << endl; return false; else if (p2guess < number) cout << "The guess is too low." << endl; else cout << "The guess is too high." << endl; return true; int main() srand(time(null));

HumanPlayer p1("kenrick"); ComputerPlayer p2("tobor"); int numtoguess = rand() % 100; while (playround(p1,p2,numtoguess)) cout << endl; cout << "Starting next round."; The key part about this method is it takes two arbitrary Player objects and then invokes the getguess() method to get the player s guess. We can implement the getguess() method different ways depending upon the player. The nice thing about polymorphism is that C++ automatically uses the method defined for the Player object passed in. In our case we ll define a Player class and a HumanPlayer and a ComputerPlayer derived from it.

FILE: Player.h #ifndef _PLAYER_ #define _PLAYER_ #include <string> class Player private: string name; Player() : name("unknown") ; Player(string n) : name(n) ; string getname() return name; ; virtual int getguess() = 0; ; #endif FILE: ComputerPlayer.h #include "Player.h" #include <iostream> class ComputerPlayer : public Player ComputerPlayer() : Player() ; ComputerPlayer(string n) : Player(n) ; int getguess(); ; FILE: ComputerPlayer.cpp #include "ComputerPlayer.h" #include <cstdlib> int ComputerPlayer::getGuess() int guess = rand() % 100; return guess; FILE: HumanPlayer.h #include "Player.h" #include <iostream> class HumanPlayer : public Player HumanPlayer() : Player() ; HumanPlayer(string n) : Player(n) ; int getguess();

; FILE: HumanPlayer.cpp #include "HumanPlayer.h" #include <iostream> int HumanPlayer::getGuess() cout << "Enter your guess. " << endl; int guess; cin >> guess; // could do input validation here return guess; We ve made a really dumb implementation for getguess() for the computer. It just guesses a random number. The human player just inputs a guess from the keyboard. When this program is run it will alternate between inputting a guess from the human from the keyboard (for player 1) and randomly guessing a number for player 2. If we wanted to make two computer players we simply change p1 to an instance of ComputerPlayer and re-run the program. We could make a smarter AI program as well and plug it right in (although it would need additional methods to tell the AI if the guess was too high or too low).