inheritance and polymorphism data structures and algorithms cs 244 brent m. dingle, ph.d. department...

85
Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University of Wisconsin – Stout Based on the book: Data Structures and Algorithms in C++ (Goodrich, Tamassia, Mount) Some content derived/taken from: http://www.stroustrup.com/Programming/ and some from C++ Through Game Programming (Dawson)

Upload: silvia-sharp

Post on 17-Jan-2016

215 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Inheritanceand Polymorphism

Data Structures and Algorithms

CS 244

Brent M. Dingle, Ph.D.

Department of Mathematics, Statistics, and Computer Science

University of Wisconsin – Stout

Based on the book: Data Structures and Algorithms in C++ (Goodrich, Tamassia, Mount)Some content derived/taken from: http://www.stroustrup.com/Programming/ and some from C++ Through Game Programming (Dawson)

Page 2: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Things to Note

• Homework 4 is Due Soon

• Homework 5 is Posted on D2L– Do NOT delay in starting it

• Do not forget to look at the Meta-Info files

Page 3: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

From Last Time– Making friends and overloading functions in your classes (FriendCritter)

– Dynamically Allocating Memory

– Memory Leaks

– Using new and delete [] with arrays

– Classes and Dynamic Memory

– Allocation Summary

– More on Classes• Constructors and Destructors with Dynamic Memory• Overloading Constructors (copy constructor)• Overloading the Assignment Operator• Graded In-Class Activity: HeapDataMember

Page 4: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

For Today

• Review– UML Hierarchy

• Inheritance and Polymorphism– Some Review and Some New stuff• Derive one class from another• Use inherited data members and member functions• Override base class member functions• Define virtual functions to enable Polymorphism• Glance at pure virtual functions to define abstract

classes

Page 5: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Marker Slide

• Any General Questions ?

• Next up– UML Hierarchy (review)– C++ Inheritance (review)– Inheritance (new)

Page 6: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Recall: Class Activity – Vehicles

• Looked like:

Pick-Up Truck Car

Vehicle

Van

Page 7: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Recall: UML Hierarchy• And we extrapolated to:• UML allows for one class to be a generalization of another

– This is called an “is a” relationship• For example, in the below a Student “is a” SimplePerson

SimplePerson - m_nameStr: string - m_idStr string

+ SimplePerson(const string& nameStr, const string& idStr); + ~SimplePerson() + print() : void + getName() : string

Friend functions + bool operator==(const SimplePerson& lhs, const SimplePerson& rhs)

Student - m_major: string - m_gradYear: int

+ Student(const string& sname, const string& sid, const string& smajor, int year); + ~Student() + print(): void + changeMajor(string newMajor) :void

Aside:This does not mean students are simple

Page 8: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Recall: C++ Hierarchy

• From UML Hierarchy we went to:

– The Object-Oriented paradigm, which C++ follows• allows for hierarchy in its classes via inheritance

– In general you will develop a base class (or parent class)• such as: SimplePerson

– From that base class you will derive a subclass (or child class)• such as: Student

– A base class may have multiple subclasses• such as: Student, Instructor, Administrator

Page 9: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Marker Slide

• Any questions on:– UML Hierarchy (review)

• Next up– C++ Inheritance (review)– Inheritance (new)

Page 10: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Recall: C++ Inheritance• Subclasses are said to specialize or extend a base

class

• Subclasses do NOT need to re-implement functions defined in the base class as the subclass inherits them– Subclasses can re-implement base class functions but

should not need to do so

• Subclasses should define and declare functions that make it a specialization of the base class

Page 11: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Recall: Class Activity – class Student• Create a C++ class Student derived

from SimplePerson– Use the code in the above slides as

appropriate• may look on D2L also for some

starter code

– Be sure to create a main() routine in a file named PersonTest.cpp to test out your new classes

• Extra Challenge– Instead of using

• g++ PersonTest.cpp SimplePerson.cpp Student.cpp

– Create a makefile to compile and build this program• Example on D2L likely (may be in

general section or examples)

SimplePerson - m_nameStr: string - m_idStr string

+ SimplePerson(const string& nameStr, const string& idStr); + ~SimplePerson() + print() : void + getName() : string

Student - m_major: string - m_gradYear: int + Student(const string& sname, const string& sid, const string& smajor, int year); + ~ Student () + print(): void + changeMajor(const string& newMajor): void

Page 12: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Marker Slide

• Any questions on:– UML Hierarchy (review)– C++ Inheritance (review)

• Next up– Inheritance (new)• Simple Boss• Overriding Boss

Page 13: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Definition: Inheritance

• Inheritance allows you to derive a new class from an existing one

– The new class is a subclass, or child, of the existing class

– The new class automatically inherits the data members and the member functions of an existing class

Page 14: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Example Use• Inheritance is useful when there is a

need for specialized versions of an existing class

• Example:– class Enemy has

• member variable: m_Damage• member function: Attack()

– Need a “Boss” type enemy that is tougher• Can extend class Enemy and add:

– a m_DamageMultiplier member variable– a SpecialAttack() member function

m_DamageMultiplier

Page 15: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

In-Class Activity: SimpleBoss• Take a couple minutes to download the example from D2L

– File: EX065_SimpleBoss.cpp• Sample run should look like:

Code Discussion/walkthrough follows

Page 16: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Simple Boss// Demonstrates inheritance// ---------------------------------------------------------------------#include <iostream>using namespace std;

// ---------------------------------------------------------------------// Declaration of class Enemy // This would normally be in the file Enemy.h// ---------------------------------------------------------------------class Enemy{ public: int m_Damage; Enemy(); void Attack() const;};

Enemy::Enemy(): m_Damage(10){ // nothing to do, the above instantiation list // already initialized m_Damage = 10}

// ---------------------------------------------------------------------void Enemy::Attack() const{ cout << "Attack inflicts " << m_Damage << " damage points!\n";}

Our typical includes and using namespace

Page 17: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Simple Boss// Demonstrates inheritance// ---------------------------------------------------------------------#include <iostream>using namespace std;

// ---------------------------------------------------------------------// Declaration of class Enemy // This would normally be in the file Enemy.h// ---------------------------------------------------------------------class Enemy{ public: int m_Damage; Enemy(); void Attack() const;};

Enemy::Enemy(): m_Damage(10){ // nothing to do, the above instantiation list // already initialized m_Damage = 10}

// ---------------------------------------------------------------------void Enemy::Attack() const{ cout << "Attack inflicts " << m_Damage << " damage points!\n";}

Declarationof class Enemy

1 public member variableConstructor1 public member function

Page 18: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Simple Boss// Demonstrates inheritance// ---------------------------------------------------------------------#include <iostream>using namespace std;

// ---------------------------------------------------------------------// Declaration of class Enemy // This would normally be in the file Enemy.h// ---------------------------------------------------------------------class Enemy{ public: int m_Damage; Enemy(); void Attack() const;};

Enemy::Enemy(): m_Damage(10){ // nothing to do, the above instantiation list // already initialized m_Damage = 10}

// ---------------------------------------------------------------------void Enemy::Attack() const{ cout << "Attack inflicts " << m_Damage << " damage points!\n";}

Constructor function of class Enemy

Notice the instantiation list : m_Damage(10)

This initializes m_Damage = 10

Same Effect As: Enemy::Enemy() { m_Damage = 10; }

Page 19: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Simple Boss// Demonstrates inheritance// ---------------------------------------------------------------------#include <iostream>using namespace std;

// ---------------------------------------------------------------------// Declaration of class Enemy // This would normally be in the file Enemy.h// ---------------------------------------------------------------------class Enemy{ public: int m_Damage; Enemy(); void Attack() const;};

Enemy::Enemy(): m_Damage(10){ // nothing to do, the above instantiation list // already initialized m_Damage = 10}

// ---------------------------------------------------------------------void Enemy::Attack() const{ cout << "Attack inflicts " << m_Damage << " damage points!\n";}

Enemy’s Attack function

The const implies no values are changed in this function (i.e. constant)

Page 20: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Declaration of class Boss// Normally this would be done in file: Boss.h// Notice it is derived from the class Enemy// ---------------------------------------------------------------------class Boss : public Enemy{ public: int m_DamageMultiplier; Boss(); void SpecialAttack() const;};

// ---------------------------------------------------------------------// Implementation of the class Boss// Normally this would be done in the file: Boss.cpp// ---------------------------------------------------------------------Boss::Boss(): m_DamageMultiplier(3){ // nothing to do here. The above instantiation list // already initialized m_DamageMultiplier = 3}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::SpecialAttack() const{ cout << "Special Attack inflicts " << (m_DamageMultiplier * m_Damage); cout << " damage points!\n";}

Declaration of class Boss derived from class Enemy and public things stay public

class Boss inherits m_Damage and Attack() from class enemy

Page 21: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Declaration of class Boss// Normally this would be done in file: Boss.h// Notice it is derived from the class Enemy// ---------------------------------------------------------------------class Boss : public Enemy{ public: int m_DamageMultiplier; Boss(); void SpecialAttack() const;};

// ---------------------------------------------------------------------// Implementation of the class Boss// Normally this would be done in the file: Boss.cpp// ---------------------------------------------------------------------Boss::Boss(): m_DamageMultiplier(3){ // nothing to do here. The above instantiation list // already initialized m_DamageMultiplier = 3}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::SpecialAttack() const{ cout << "Special Attack inflicts " << (m_DamageMultiplier * m_Damage); cout << " damage points!\n";}

Declaration of class Boss derived from class Enemy and public things stay public

class Boss inherits m_Damage and Attack() from class enemy

It extends the class by adding the membersm_DamageMultiplier and SpecialAttack()

Page 22: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Declaration of class Boss// Normally this would be done in file: Boss.h// Notice it is derived from the class Enemy// ---------------------------------------------------------------------class Boss : public Enemy{ public: int m_DamageMultiplier; Boss(); void SpecialAttack() const;};

// ---------------------------------------------------------------------// Implementation of the class Boss// Normally this would be done in the file: Boss.cpp// ---------------------------------------------------------------------Boss::Boss(): m_DamageMultiplier(3){ // nothing to do here. The above instantiation list // already initialized m_DamageMultiplier = 3}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::SpecialAttack() const{ cout << "Special Attack inflicts " << (m_DamageMultiplier * m_Damage); cout << " damage points!\n";}

Declaration of class Boss derived from class Enemy and public things stay public

class Boss inherits m_Damage and Attack() from class enemy

It extends the class by adding the membersm_DamageMultiplier and SpecialAttack()

Public Service Message

• Constructors• Copy Constructors• Destructors• Overloaded assignment operators

are NOT inherited from the base class

Page 23: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Declaration of class Boss// Normally this would be done in file: Boss.h// Notice it is derived from the class Enemy// ---------------------------------------------------------------------class Boss : public Enemy{ public: int m_DamageMultiplier; Boss(); void SpecialAttack() const;};

// ---------------------------------------------------------------------// Implementation of the class Boss// Normally this would be done in the file: Boss.cpp// ---------------------------------------------------------------------Boss::Boss(): m_DamageMultiplier(3){ // nothing to do here. The above instantiation list // already initialized m_DamageMultiplier = 3}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::SpecialAttack() const{ cout << "Special Attack inflicts " << (m_DamageMultiplier * m_Damage); cout << " damage points!\n";}

Constructor of the Boss class.

It too has an instantiation listWhich initializes m_DamageMultiplier = 3

But what is the value of m_Damage?

How?

Page 24: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Declaration of class Boss// Normally this would be done in file: Boss.h// Notice it is derived from the class Enemy// ---------------------------------------------------------------------class Boss : public Enemy{ public: int m_DamageMultiplier; Boss(); void SpecialAttack() const;};

// ---------------------------------------------------------------------// Implementation of the class Boss// Normally this would be done in the file: Boss.cpp// ---------------------------------------------------------------------Boss::Boss(): m_DamageMultiplier(3){ // nothing to do here. The above instantiation list // already initialized m_DamageMultiplier = 3}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::SpecialAttack() const{ cout << "Special Attack inflicts " << (m_DamageMultiplier * m_Damage); cout << " damage points!\n";}

Constructor of the Boss class.

It too has an instantiation listWhich initializes m_DamageMultiplier = 3

But what is the value of m_Damage?

How?

Side Point ExerciseTry the following code/program out and see what happens:struct A{ A() {cout << "A() C-tor" << endl;} ~A(){cout << "~A() D-tor" << endl;} };

struct B : public A{ B(){cout << "B() C-tor" << endl;} ~B(){cout << "~B() D-tor" << endl;} };

int main(){ B b; }

Page 25: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Declaration of class Boss// Normally this would be done in file: Boss.h// Notice it is derived from the class Enemy// ---------------------------------------------------------------------class Boss : public Enemy{ public: int m_DamageMultiplier; Boss(); void SpecialAttack() const;};

// ---------------------------------------------------------------------// Implementation of the class Boss// Normally this would be done in the file: Boss.cpp// ---------------------------------------------------------------------Boss::Boss(): m_DamageMultiplier(3){ // nothing to do here. The above instantiation list // already initialized m_DamageMultiplier = 3}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::SpecialAttack() const{ cout << "Special Attack inflicts " << (m_DamageMultiplier * m_Damage); cout << " damage points!\n";}

Side Point ExerciseTry the following code/program out and see what happens:struct A{ A() {cout << "A() C-tor" << endl;} ~A(){cout << "~A() D-tor" << endl;} };

struct B : public A{ B(){cout << "B() C-tor" << endl;} ~B(){cout << "~B() D-tor" << endl;} };

int main(){ B b; }

struct A has a “default” constructor i.e. one with no parameters

struct B’s constructor will automatically callthe default constructor for A prior to running its own constructor.

Page 26: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Declaration of class Boss// Normally this would be done in file: Boss.h// Notice it is derived from the class Enemy// ---------------------------------------------------------------------class Boss : public Enemy{ public: int m_DamageMultiplier; Boss(); void SpecialAttack() const;};

// ---------------------------------------------------------------------// Implementation of the class Boss// Normally this would be done in the file: Boss.cpp// ---------------------------------------------------------------------Boss::Boss(): m_DamageMultiplier(3){ // nothing to do here. The above instantiation list // already initialized m_DamageMultiplier = 3}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::SpecialAttack() const{ cout << "Special Attack inflicts " << (m_DamageMultiplier * m_Damage); cout << " damage points!\n";}

Side Point ExerciseTry the following code/program out and see what happens:struct A{ A() {cout << "A() C-tor" << endl;} ~A(){cout << "~A() D-tor" << endl;} };

struct B : public A{ B(){cout << "B() C-tor" << endl;} ~B(){cout << "~B() D-tor" << endl;} };

int main(){ B b; }

struct A has a “default” constructor i.e. one with 0 parameters

struct B’s constructor will automatically callthe default constructor for A prior to running its own constructor.

And we see that in the output below

Page 27: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Declaration of class Boss// Normally this would be done in file: Boss.h// Notice it is derived from the class Enemy// ---------------------------------------------------------------------class Boss : public Enemy{ public: int m_DamageMultiplier; Boss(); void SpecialAttack() const;};

// ---------------------------------------------------------------------// Implementation of the class Boss// Normally this would be done in the file: Boss.cpp// ---------------------------------------------------------------------Boss::Boss(): m_DamageMultiplier(3){ // nothing to do here. The above instantiation list // already initialized m_DamageMultiplier = 3}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::SpecialAttack() const{ cout << "Special Attack inflicts " << (m_DamageMultiplier * m_Damage); cout << " damage points!\n";}

Side Point ExerciseTry the following code/program out and see what happens:struct A{ A() {cout << "A() C-tor" << endl;} ~A(){cout << "~A() D-tor" << endl;} };

struct B : public A{ B(){cout << "B() C-tor" << endl;} ~B(){cout << "~B() D-tor" << endl;} };

int main(){ B b; }

The destructors are called in reverse order.

When B’s destructor completesthen A’s is called automatically.

Think house construction:A = foundation, B = first floorCreate house = build foundation, then 1st floorDestroy house = dest 1st floor, then foundation

Page 28: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Declaration of class Boss// Normally this would be done in file: Boss.h// Notice it is derived from the class Enemy// ---------------------------------------------------------------------class Boss : public Enemy{ public: int m_DamageMultiplier; Boss(); void SpecialAttack() const;};

// ---------------------------------------------------------------------// Implementation of the class Boss// Normally this would be done in the file: Boss.cpp// ---------------------------------------------------------------------Boss::Boss(): m_DamageMultiplier(3){ // nothing to do here. The above instantiation list // already initialized m_DamageMultiplier = 3}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::SpecialAttack() const{ cout << "Special Attack inflicts " << (m_DamageMultiplier * m_Damage); cout << " damage points!\n";}

But what is the value of m_Damage?How?So value of m_Damage is set to 10because Enemy’s default constructor is automatically called by Boss’s constructor before it executes its own body of code.

Page 29: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// Declaration of class Boss// Normally this would be done in file: Boss.h// Notice it is derived from the class Enemy// ---------------------------------------------------------------------class Boss : public Enemy{ public: int m_DamageMultiplier; Boss(); void SpecialAttack() const;};

// ---------------------------------------------------------------------// Implementation of the class Boss// Normally this would be done in the file: Boss.cpp// ---------------------------------------------------------------------Boss::Boss(): m_DamageMultiplier(3){ // nothing to do here. The above instantiation list // already initialized m_DamageMultiplier = 3}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::SpecialAttack() const{ cout << "Special Attack inflicts " << (m_DamageMultiplier * m_Damage); cout << " damage points!\n";}

SpecialAttack functionagain const implies no values will change in this function (i.e constant)

Page 30: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// main function// Normally this would be found in a separate .cpp file// perhaps named BossTest.cpp// ---------------------------------------------------------------------int main(){ cout << "Creating an enemy.\n"; Enemy enemy1;

enemy1.Attack();

cout << "\nCreating a boss.\n";

Boss boss1; boss1.Attack(); boss1.SpecialAttack();

return 0;}

The main() function

Creates a variable of type EnemyAnd calls its Atttack() function

Page 31: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Simple Boss// ---------------------------------------------------------------------// main function// Normally this would be found in a separate .cpp file// perhaps named BossTest.cpp// ---------------------------------------------------------------------int main(){ cout << "Creating an enemy.\n"; Enemy enemy1;

enemy1.Attack();

cout << "\nCreating a boss.\n";

Boss boss1; boss1.Attack(); boss1.SpecialAttack();

return 0;}

The main() function

It then creates a variable of type Bossand calls its Attack and SpecialAttack functions

Page 32: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Marker Slide• Any questions on:– UML Hierarchy (review)– C++ Inheritance (review)– Inheritance (new)

• Simple Boss

• Next up– Inheritance (new)

• Overriding Boss

– Polymorphism (new)• Polymorphic Bad Guy

Page 33: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

In-Class Activity: Overriding Boss• Take a couple minutes to download the example from D2L

– File: EX069_OverridingBoss.cpp• Sample run should look like:

Code Discussion/walkthrough follows

Page 34: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss//Overriding Boss//Demonstrates calling and overriding base member functions

#include <iostream>using namespace std;

// ---------------------------------------------------------------------// Enemy Interface Declaration // Typically found in Enemy.h, // everything is grouped together here for ease of presentation// ---------------------------------------------------------------------

class Enemy{ public: Enemy(int damage = 10); void virtual Taunt() const; //made virtual to be overridden void virtual Attack() const; //made virtual to be overridden private: int m_Damage;};

Standard include for IO

Using standard namespace

Page 35: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss//Overriding Boss//Demonstrates calling and overriding base member functions

#include <iostream>using namespace std;

// ---------------------------------------------------------------------// Enemy Interface Declaration // Typically found in Enemy.h, // everything is grouped together here for ease of presentation// ---------------------------------------------------------------------

class Enemy{ public: Enemy(int damage = 10); void virtual Taunt() const; //made virtual to be overridden void virtual Attack() const; //made virtual to be overridden private: int m_Damage;};

Class Enemy

Constructor sets default value for damage to 10

Page 36: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss//Overriding Boss//Demonstrates calling and overriding base member functions

#include <iostream>using namespace std;

// ---------------------------------------------------------------------// Enemy Interface Declaration // Typically found in Enemy.h, // everything is grouped together here for ease of presentation// ---------------------------------------------------------------------

class Enemy{ public: Enemy(int damage = 10); void virtual Taunt() const; //made virtual to be overridden void virtual Attack() const; //made virtual to be overridden private: int m_Damage;};

Enemy(int damage = 10)

Works like TWO constructors

The first has zero parameters Enemy someGuy;

The compiler will automatically change that to be the same as: Enemy someGuy(10);

Page 37: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss//Overriding Boss//Demonstrates calling and overriding base member functions

#include <iostream>using namespace std;

// ---------------------------------------------------------------------// Enemy Interface Declaration // Typically found in Enemy.h, // everything is grouped together here for ease of presentation// ---------------------------------------------------------------------

class Enemy{ public: Enemy(int damage = 10); void virtual Taunt() const; //made virtual to be overridden void virtual Attack() const; //made virtual to be overridden private: int m_Damage;};

Enemy(int damage = 10)

Works like TWO constructors

The second has one parameters Enemy someGuy(88);

with results as would be expected.

Page 38: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss//Overriding Boss//Demonstrates calling and overriding base member functions

#include <iostream>using namespace std;

// ---------------------------------------------------------------------// Enemy Interface Declaration // Typically found in Enemy.h, // everything is grouped together here for ease of presentation// ---------------------------------------------------------------------

class Enemy{ public: Enemy(int damage = 10); void virtual Taunt() const; //made virtual to be overridden void virtual Attack() const; //made virtual to be overridden private: int m_Damage;};

Virtual Functions

The keyword virtual means these functions are intended to be overridden by subclasses.

This supports polymorphism.

Page 39: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss// ---------------------------------------------------------------------// Enemy Implementation Definition // Typically found in Enemy.cpp, // everything is grouped together here for ease of presentation// ---------------------------------------------------------------------// ---------------------------------------------------------------------// Constructor// ---------------------------------------------------------------------

Enemy::Enemy(int damage):m_Damage(damage){ // nothing left to do

}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------

void Enemy::Taunt() const{ cout << "The enemy says he will fight you.\n";}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------

void Enemy::Attack() const{ cout << "Attack! Inflicts " << m_Damage << " damage points.";}

Note the instantiation list :m_Damage(damage)

This is the same as saying m_Damage = damage;

in the body of the constructor

Page 40: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss// ---------------------------------------------------------------------// Enemy Implementation Definition // Typically found in Enemy.cpp, // everything is grouped together here for ease of presentation// ---------------------------------------------------------------------// ---------------------------------------------------------------------// Constructor// ---------------------------------------------------------------------

Enemy::Enemy(int damage):m_Damage(damage){ // nothing left to do

}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------

void Enemy::Taunt() const{ cout << "The enemy says he will fight you.\n";}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------

void Enemy::Attack() const{ cout << "Attack! Inflicts " << m_Damage << " damage points.";}

Member functions with basic output lines to the screen.

Recall these were declared as virtual

Note the words used as they will not be the same as the soon to be revealed “Boss” class

Page 41: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss// ---------------------------------------------------------------------// ---------------------------------------------------------------------// Interface Declaration for // Boss class derived from Enemy class// Again typically this would be in Boss.h// ---------------------------------------------------------------------class Boss : public Enemy{ public: Boss(int damage = 30); void virtual Taunt() const; //optional use of keyword virtual void virtual Attack() const; //optional use of keyword virtual};

class Enemy{ public: Enemy(int damage = 10); void virtual Taunt() const; //made virtual to be overridden void virtual Attack() const; //made virtual to be overridden private: int m_Damage;};Interface for Boss class derived from Enemy

Notice almost same as Enemy class.

Constructor initializes damage to 30

virtual keyword kept

No re-declaration of member variable: m_Damage

Page 42: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss// ---------------------------------------------------------------------// ---------------------------------------------------------------------// Implementation Definition of Boss class// Again typically this would be in Boss.cpp// ---------------------------------------------------------------------// ---------------------------------------------------------------------// Boss's Constructor// ---------------------------------------------------------------------

Boss::Boss(int damage): Enemy(damage) // call base class constructor with argument{} For the Boss’s constructor the instantiation list does something special:

It calls the base class constructor sending it the damage parameter

This is one of the few ways you can ever directly “call” a class’s constructor

In thought this is same as: Boss:Boss(int damage) { Enemy::Enemy(damage); you should not actually do this

}

Page 43: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::Taunt() const //override base class member function{ cout << "The boss says he will end your pitiful existence.\n";}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::Attack() const //override base class member function{ Enemy::Attack(); //call base class member function cout << " And laughs heartily at you.\n";}

Here are the overridden virtual functions

Notice the output is different than that of the Enemy functions of the same name

void Enemy::Taunt() const{ cout << "The enemy says he will fight you.\n";}

void Enemy::Attack() const{ cout << "Attack! Inflicts " << m_Damage << " damage points.";}

Page 44: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::Taunt() const //override base class member function{ cout << "The boss says he will end your pitiful existence.\n";}

// ---------------------------------------------------------------------// ---------------------------------------------------------------------void Boss::Attack() const //override base class member function{ Enemy::Attack(); //call base class member function cout << " And laughs heartily at you.\n";}

Other point of note

The Boss::Attack functionfirst calls the base class’s Attack function

and then adds an extra message after it

void Enemy::Taunt() const{ cout << "The enemy says he will fight you.\n";}

void Enemy::Attack() const{ cout << "Attack! Inflicts " << m_Damage << " damage points.";}

Page 45: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Overriding Boss// ---------------------------------------------------------------------// main - it all begins here // This would also typically be in a separate file, e.g. BossTester.cpp// ---------------------------------------------------------------------

int main(){ cout << "Enemy object:\n"; Enemy anEnemy; anEnemy.Taunt(); anEnemy.Attack();

cout << "\n\nBoss object:\n"; Boss aBoss; aBoss.Taunt(); aBoss.Attack(); return 0;}

The main() function

Creates an “Enemy”

Creates a “Boss”

Compare the output of the Taunt and Attack Functions

Page 46: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Marker Slide• Any questions on:– UML Hierarchy (review)– C++ Inheritance (review)– Inheritance (new)

• Simple Boss• Overriding Boss

• Next up– Polymorphism (new)

• Polymorphic Bad Guy

– Blackjack Game

Page 47: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Polymorphism• Conversational definition of Polymorphism:– A member function will produce different results

depending on the type of object for which it is being called

• Example– 10 bad guys face the player– Each of a different class type– Call the attack() function for each and get 10

different (class specific attacks)• requires use of keyword virtual

Page 48: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

In-Class Activity: Poly Bad Guy• Take a couple minutes to download the example from D2L

– File: EX072_PolymorphBadGuy.cpp• Sample run should look like:

Code Discussion/walkthrough follows

Page 49: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// Polymorphic Bad Guy// Demonstrates calling member functions dynamically// --------------------------------------------------------------------#include <iostream>using namespace std;

// --------------------------------------------------------------------// --------------------------------------------------------------------class Enemy{ public: Enemy(int damage = 10); virtual ~Enemy(); void virtual Attack() const; protected: int* mp_Damage;};

Code setup is similar to previous example

Note a destructor is declaredand the use of virtual

and the m_Damage is now a pointernamed mp_Damage

Page 50: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// --------------------------------------------------------------------Enemy::Enemy(int damage){ mp_Damage = new int(damage);}

// --------------------------------------------------------------------// --------------------------------------------------------------------Enemy::~Enemy(){ cout << "In Enemy destructor, deleting mp_Damage.\n"; delete mp_Damage; mp_Damage = 0;}

Constructor is dynamically allocating memory

Page 51: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// --------------------------------------------------------------------Enemy::Enemy(int damage){ mp_Damage = new int(damage);}

// --------------------------------------------------------------------// --------------------------------------------------------------------Enemy::~Enemy(){ cout << "In Enemy destructor, deleting mp_Damage.\n"; delete mp_Damage; mp_Damage = NULL;}

Destructoris freeing/deleting the dynamically allocated memory

and setting the pointer to NULL

Page 52: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// --------------------------------------------------------------------void Enemy::Attack() const{ cout << "An enemy attacks and inflicts " << *mp_Damage << " damage points.";}

Outputs the damage of the attack.

Note the * dereferences the mp_Damage pointer variable

Page 53: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// --------------------------------------------------------------------class Boss : public Enemy{ public: Boss(int multiplier = 3); virtual ~Boss(); void virtual Attack() const; protected: int* mp_Multiplier;};

Interface Declaration for Boss class

Again has a destructorand uses the keyword virtual

The damage multiplier member variable is a pointer to type int

Page 54: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// --------------------------------------------------------------------Boss::Boss(int multiplier){ mp_Multiplier = new int(multiplier);}

// --------------------------------------------------------------------// --------------------------------------------------------------------Boss::~Boss(){ cout << "In Boss destructor, deleting mp_Multiplier.\n"; delete mp_Multiplier; mp_Multiplier = NULL;}

The Boss’s constructor allocates memory for the mp_Multiplier

Recall the Enemy’s constructor is automatically called prior to the running of the Boss’s constructor

Page 55: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// --------------------------------------------------------------------Boss::Boss(int multiplier){ mp_Multiplier = new int(multiplier);}

// --------------------------------------------------------------------// --------------------------------------------------------------------Boss::~Boss(){ cout << "In Boss destructor, deleting mp_Multiplier.\n"; delete mp_Multiplier; mp_Multiplier = NULL;}

The Boss’s destructor frees the memory used by the mp_Multiplier pointer variable and sets it to NULL.

Recall the Enemy’s destructor will be called automatically after the Boss’s destructor executes

Page 56: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guyvoid Boss::Attack() const{ cout << "A boss attacks and inflicts " << (*mp_Damage) * (*mp_Multiplier) << " damage points.";}

The Boss’s attack function

Notice the output is significantly different than that of a basic Enemy

Note also the dereferencing of the pointer variables using *

Page 57: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// main - it all begins here// --------------------------------------------------------------------int main(){ cout << "Calling Attack() on Boss object through pointer to Enemy:\n"; Enemy* pBadGuy = new Boss(); pBadGuy->Attack();

cout << "\n\nDeleting pointer to Enemy:\n"; delete pBadGuy; pBadGuy = NULL; return 0;}

We declare a pointer to class Enemy

Page 58: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// main - it all begins here// --------------------------------------------------------------------int main(){ cout << "Calling Attack() on Boss object through pointer to Enemy:\n"; Enemy* pBadGuy = new Boss(); pBadGuy->Attack();

cout << "\n\nDeleting pointer to Enemy:\n"; delete pBadGuy; pBadGuy = NULL; return 0;}

We declare a pointer to class Enemy

But we allocate a class Boss

Page 59: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// main - it all begins here// --------------------------------------------------------------------int main(){ cout << "Calling Attack() on Boss object through pointer to Enemy:\n"; Enemy* pBadGuy = new Boss(); pBadGuy->Attack();

cout << "\n\nDeleting pointer to Enemy:\n"; delete pBadGuy; pBadGuy = NULL; return 0;}

We declare a pointer to class Enemy

But we allocate a class Boss

So which Attack() function executes here?

Page 60: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// main - it all begins here// --------------------------------------------------------------------int main(){ cout << "Calling Attack() on Boss object through pointer to Enemy:\n"; Enemy* pBadGuy = new Boss(); pBadGuy->Attack();

cout << "\n\nDeleting pointer to Enemy:\n"; delete pBadGuy; pBadGuy = NULL; return 0;}

We declare a pointer to class Enemy

But we allocate a class Boss

So which Attack() function executes here?

By Polymorphism and the use of the keyword virtual

Boss’s Attack function will “magically” be executed

Page 61: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// main - it all begins here// --------------------------------------------------------------------int main(){ cout << "Calling Attack() on Boss object through pointer to Enemy:\n"; Enemy* pBadGuy = new Boss(); pBadGuy->Attack();

cout << "\n\nDeleting pointer to Enemy:\n"; delete pBadGuy; pBadGuy = NULL; return 0;}

A potential problem exists when you use a pointer to a base class to point to an object of a derived class.

When you delete the pointer, only the base class’ destructor will be called for the object.

This could lead to disastrous resultsbecause the derived class’ destructor might need to free memory (as the destructor for Boss does).

The solution is to make the base class’ destructor virtual.

That way, the derived class’ destructor is called, which (as always) leads to the calling the base class’ destructor, giving every class the chance to clean up after itself.

Page 62: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// main - it all begins here// --------------------------------------------------------------------int main(){ cout << "Calling Attack() on Boss object through pointer to Enemy:\n"; Enemy* pBadGuy = new Boss(); pBadGuy->Attack();

cout << "\n\nDeleting pointer to Enemy:\n"; delete pBadGuy; pBadGuy = NULL; return 0;}

A potential problem exists when you use a pointer to a base class to point to an object of a derived class.

When you delete the pointer, only the base class’ destructor will be called for the object. (in this case Enemy is the base class)

This could lead to disastrous resultsbecause the derived class’ destructor might need to free memory (as the destructor for Boss does).

The solution is to make the base class’ destructor virtual.

That way, the derived class’ destructor is called, which (as always) leads to the calling the base class’ destructor, giving every class the chance to clean up after itself.

Page 63: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// main - it all begins here// --------------------------------------------------------------------int main(){ cout << "Calling Attack() on Boss object through pointer to Enemy:\n"; Enemy* pBadGuy = new Boss(); pBadGuy->Attack();

cout << "\n\nDeleting pointer to Enemy:\n"; delete pBadGuy; pBadGuy = NULL; return 0;}

A potential problem exists when you use a pointer to a base class to point to an object of a derived class.

When you delete the pointer, only the base class’ destructor will be called for the object.

This could lead to disastrous resultsbecause the derived class’ destructor might need to free memory (as the destructor for Boss does).

The solution is to make the base class’ destructor virtual.

That way, the derived class’ destructor is called, which (as always) leads to the calling the base class’ destructor, giving every class the chance to clean up after itself.

class Enemy{ public: Enemy(int damage = 10); virtual ~Enemy(); void virtual Attack() const; protected: int* mp_Damage;};

Page 64: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Looking at Poly Bad Guy// --------------------------------------------------------------------// main - it all begins here// --------------------------------------------------------------------int main(){ cout << "Calling Attack() on Boss object through pointer to Enemy:\n"; Enemy* pBadGuy = new Boss(); pBadGuy->Attack();

cout << "\n\nDeleting pointer to Enemy:\n"; delete pBadGuy; pBadGuy = NULL; return 0;}

A potential problem exists when you use a pointer to a base class to point to an object of a derived class.

When you delete the pointer, only the base class’ destructor will be called for the object.

This could lead to disastrous resultsbecause the derived class’ destructor might need to free memory (as the destructor for Boss does).

The solution is to make the base class’ destructor virtual.

That way, the derived class’ destructor is called, which leads to the calling of the base class’ destructor, giving every class the chance to clean up after itself.

Page 65: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Independent Activity: Poly Bad Guy

• On your own– To see what the keyword virtual ‘really’ does:• Take the previous program• Remove the keyword virtual from everywhere it

appears• See what changes

Page 66: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Independent Activity: Pure Virtual

• On your own– Abstract Class– Pure Virtual Functions

– Download and play with• EX074_AbstractCreature.cpp

Page 67: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Marker Slide• Any questions on:– UML Hierarchy (review)– C++ Inheritance (review)– Inheritance (new)

• Simple Boss• Overriding Boss

– Polymorphism (new)• Polymorphic Bad Guy

• Next up– Program Design

• Blackjack Game

Page 68: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Blackjack Game

• Standard game of Blackjack– also called 21

• Object– Obtain the set of cards closest to 21 • without going over

Page 69: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Blackjack Game Classes• Useful C++ classes to have around for the game

Page 70: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Classes: Inheritance Relations• Generic player is shaded to indicate it is an abstract class

– i.e. all virtual functions, base class only, – not intended to be instantiated

Page 71: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Classes: More Details

• Cards:– real-life cards– don’t copy when you deal it from he deck,

move it to a hand– allocate them on the heap (free store)

• Hand– vector of pointers to Card objects– cards moving from hand to hand are really

pointers that are being copied and destroyed

Page 72: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Classes: More Details• Players– Humans and Computer– Each really is a “Hand”– Computer will be the dealer (aka House)

• which has unique rules to determine “hit” or “stay”

– Humans will be players• requires human input for “hit” or “stay”

• Deck– Similar to a hand– Starts as all 52 cards (randomly ordered)– Needs to be able to “deal” cards to player and the house

objects

Page 73: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Card Class

Page 74: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Hand Class

Page 75: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

GenericPlayer (abstract) Class

Page 76: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Player Class

Page 77: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

House Class

Page 78: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Deck Class

Page 79: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Game Class

Page 80: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Game Flow• Deal players and the house 2 initial cards• Hide the house’s first card (facedown)• Display players’ and house’s hands

• Deal additional cards to players

• Reveal House’s first card• Deal additional cards to house

• If House busted– Everyone who is not busted wins

• Else– Each non-busted player above house’s total wins– Players with total over 21, or less than equal to house lose

Page 81: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

main() function of Blackjack Gameint main(){ cout << "\t\tWelcome to Blackjack!\n\n"; int numPlayers = 0; while (numPlayers < 1 || numPlayers > 7) { cout << "How many players? (1 - 7): "; cin >> numPlayers; }

vector<string> names; string name; for (int i = 0; i < numPlayers; ++i) { cout << "Enter player name: "; cin >> name; names.push_back(name); } cout << endl;

// the game loop Game aGame(names); char again = 'y'; while (again != 'n' && again != 'N') { aGame.Play(); cout << "\nDo you want to play again? (Y/N): "; cin >> again; }

return 0;}

Page 82: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Marker Slide• Any Questions on:

• Any questions on:– UML Hierarchy (review)– C++ Inheritance (review)– Inheritance (new)

• Simple Boss• Overriding Boss

– Polymorphism (new)• Polymorphic Bad Guy

– Program Design• Blackjack Game

• Next up– Free Play --- and an in-class assignment

Page 83: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Graded In-Class Activity: Blackjack• Implement and run a Blackjack program based on the design just

discussed– Starter code (and one possible solution) is on D2L

• Download the file:– ICA020_broken_Blackjack.cpp

• Rename it: Blackjack.cpp• Fix the program as indicated

– Put your name and today’s date in the lead comments– Compile it– Run it– When satisfied with it (or class ends) upload the resulting FIXED code to the

appropriate D2L dropbox• You can work in groups

– BUT each individual must submit something to D2L

You may create a set ofsource files and possibly a makefileto solve this problem, but it is not required

Page 84: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

Free Play – Things to Work On

• Graded In-Class Activity:• Homework 4• Homework 5

• Various In-Class Activities to revisit

Page 85: Inheritance and Polymorphism Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University

The End

• Or is it?