cs 240chapter 8 – class relationshipspage 53 chapter 8 class relationships up to this point, the...

55
CS 240 CS 240 Chapter 8 – Class Relationships Chapter 8 – Class Relationships Page Page 1 Chapter 8 Chapter 8 Class Relationships Class Relationships Up to this point, the C++ classes that we’ve used have Up to this point, the C++ classes that we’ve used have been little more than elaborate structs. been little more than elaborate structs. We’re now going to examine some of the features of C+ We’re now going to examine some of the features of C+ + classes that expand the language’s object-oriented + classes that expand the language’s object-oriented capabilities: capabilities: Inheritance Inheritance Virtual Functions Virtual Functions Class Templates Class Templates Function Templates Function Templates Overloaded Operators Overloaded Operators

Upload: percival-pope

Post on 14-Dec-2015

213 views

Category:

Documents


0 download

TRANSCRIPT

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 11

Chapter 8Chapter 8Class RelationshipsClass Relationships

Up to this point, the C++ classes that we’ve Up to this point, the C++ classes that we’ve used have been little more than elaborate used have been little more than elaborate structs.structs.We’re now going to examine some of the We’re now going to examine some of the features of C++ classes that expand the features of C++ classes that expand the language’s object-oriented capabilities:language’s object-oriented capabilities:

InheritanceInheritance

Virtual FunctionsVirtual Functions

Class TemplatesClass Templates

Function TemplatesFunction Templates

Overloaded OperatorsOverloaded Operators

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 22

class X: public A

X’s public members

X’s protected members

X’s private members

A’s public members

A’s protected members

class Y: protected A

Y’s public members

Y’s protected members

Y’s private members

A’s public members

A’s protected members

class Z: private A

Z’s public members

Z’s private members

Z’s protected members

A’s public members

A’s protected members

InheritanceInheritanceWhen a new class is merely an When a new class is merely an extension of an existing class, extension of an existing class, the class may be defined as a the class may be defined as a “derived” class, which “derived” class, which “inherits” from the existing “inherits” from the existing class.class.

class A

A’s public members

A’s protected members

A’s private members

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 33

////////////////////////////////////////////////// Class definition file: Account.h //// //// In this header file, a class is defined to //// hold information about a bank Account. //// Notice that the only real piece of data //// inside an object of this class is a single //// floating-point number that represents the //// Account's current balance. Again, the //// idea of forming a class like this is to //// hide the information so that it can only //// be accessed through precisely specified //// means, to centralize those means so that //// modifying them at a later date can be sim- //// plified, and to make it easy to formulate //// slight variations of the Account class //// (e.g., a checking Account that accumulates //// interest, a savings Account, etc.). //////////////////////////////////////////////////#ifndef ACCT_H#include <iostream>using namespace std;

class Account{ public: // Class constructors Account(); Account(float initialBalance); Account(const Account &a);

// Function members float deposit(float amount); float withdraw(float amount); float getBalance(); Account& operator = (const Account &a);

protected: // Data member float balance;};#define ACCT_H#endif

///////////////////////////////////////////////// Class implementation file: Account.cpp //// //// The implementations of the member func- //// tions of the Account class are contained //// in this program file. /////////////////////////////////////////////////

#include "Account.h" #include <iostream>using namespace std;

// Default Constructor: Handles the creation //// of an Account with an unspecified initial //// balance. //Account::Account(){ balance = 0.00F;}

Inheritance Example #1: Bank AccountsInheritance Example #1: Bank Accounts

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 44

// Initializing Constructor: Handles the //// creation of an Account with a specified //// initial balance. //Account::Account(float initialBalance){ balance = initialBalance;}

// Copy Constructor: Handles the creation //// of an Account that is a duplicate of //// the parameterized Account. //Account::Account(const Account &a){ balance = a.balance;}

// Deposit Member Function: Adds a depo- //// sited amt to the balance of an Account. //float Account::deposit(float amount){ balance = balance + amount; return balance;}

// Withdraw Member Function: Subtracts a //// withdrawal amt from the balance of an //// Account, returning the modified balance //// if there are sufficient funds and a //// neg. value if insufficient funds exist. //

float Account::withdraw(float amount){ if (amount > balance) return -1.0F; else { balance = balance - amount; return balance; }}

// GetBalance Member Function: Retrieves //// the Account balance. This is the only //// way for a function that is not a //// member function of the Account class //// (or one of its derived classes) to //// access the current Account balance. //float Account::getBalance(){ return balance;}

// Assignment Operator: Overloads the //// assignment operator, so a variable of //// type Account can be used in an assign- //// ment statement. //Account& Account::operator = (const Account &a){ balance = a.balance; return *this;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 55

/////////////////////////////////////////////// Class definition file: CreditAccount.h //// In this header file, a subclass of the //// Account class is defined to hold infor- //// mation about a CreditAccount. All of //// the members of the Account class are //// members of the CreditAccount subclass, //// and the subclass has three additional //// members: an initializing constructor, //// one data member to hold the CreditAc- //// count's daily rate for finance charges, //// and one public member function to apply //// the finance charges to the balance. ///////////////////////////////////////////////#ifndef CRED_ACCT_H#include "Account.h" #include <iostream>using namespace std;class CreditAccount: public Account{ public: // Class constructor CreditAccount(float initialBalance, float finChgRate); // Member function float withdraw(float amount); void applyFinanceCharge();

protected: // Data member float dailyFinChgRate;};#define CRED_ACCT_H#endif

//////////////////////////////////////////////////// Class implementation file: CreditAccount.cpp //// //// This program file contains the implementa- //// tions of the member functions of the Credit- //// Account subclass of the account class. ////////////////////////////////////////////////////#include "CreditAccount.h"

// The initializing constructor for the Credit- //// Account class invokes the initializing con- //// structor for the Account class, which ini- //// tializes the balance data member. It then //// gives an initial value to the data member //// representing the finance charge rate. //CreditAccount::CreditAccount(float initialBalance, float finChgRate): Account(initialBalance){ dailyFinChgRate = finChgRate;}

// The withdraw member function for the Credit- //// Account subclass supercedes the withdraw //// member function for the Account superclass; //// it subtracts a withdrawal amount from the //// balance of a CreditAccount, returning the //// resulting balance (even if it's negative). //float CreditAccount::withdraw(float amount){ balance -= amount; return balance;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 66

class CreditAccount: public Account

PUBLIC:withdraw

applyFinanceCharge PROTECTED:dailyFinChgRate

depositwithdraw

getBalance= operator

balance

////////////////////////////////////////////////// The applyFinanceCharge member function //// updates a CreditAccount's balance by //// taking the product of the CreditAccount's //// finance charge rate and the amount //// currently owed on the CreditAccount, and //// subtracting that product from the balance. //////////////////////////////////////////////////void CreditAccount::applyFinanceCharge(){ if (getBalance() < 0.0F) withdraw(-1.0F*getBalance()*dailyFinChgRate);}

class AccountPUBLIC:deposit

withdrawgetBalance= operator

PROTECTED:balance

Note that Note that CreditAccouCreditAccou

nt has nt has access to access to

bothboth withdrawwithdraw

functions!functions!

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 77

/////////////////////////////////////////////// Class definition file: DebitAccount.h //// //// In this header file, a subclass of the //// Account class is defined to hold infor- //// mation about a DebitAccount. All of //// the members of the Account class are //// members of the DebitAccount subclass, //// and the subclass has 3 additional mem- //// bers: an initializing constructor, one //// data member to hold the DebitAccount's //// daily interest rate, and one public //// member function to apply this interest //// rate to the current balance. ///////////////////////////////////////////////#ifndef DEB_ACCT_H#include "Account.h" #include <iostream>using namespace std;class DebitAccount: public Account{ public: // Class constructor DebitAccount(float initialBalance, float intRate);

//Member function void compoundInterest();

protected: // Data member float dailyIntRate;};#define DEB_ACCT_H#endif

///////////////////////////////////////////////////// Class implementation file: DebitAccount.cpp //// //// This program file contains the implementa- //// tions of the member functions of the Debit- //// Account subclass of the Account class. /////////////////////////////////////////////////////#include "DebitAccount.h"#include <iostream>using namespace std;

// The initializing constructor for the Debit- //// Account class invokes the initializing con- //// structor for the Account class, which ini- //// tializes the balance data member. It then //// gives an initial value to the interest data //// member. //DebitAccount::DebitAccount(float initialBalance, float intRate): Account(initialBalance){ dailyIntRate = intRate;}

// The compoundInterest function updates a //// DebitAccount's balance by taking the //// product of the incoming interest rate and //// the DebitAccount's balance, and adding //// that product to the balance. //void DebitAccount::compoundInterest(){ if (getBalance() > 0.0F) deposit(getBalance() * dailyIntRate);}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 88

class DebitAccount: public Account

PUBLIC:compoundInterest

PROTECTED:dailyIntRate

depositwithdraw

getBalance= operator

balance

class AccountPUBLIC:deposit

withdrawgetBalance= operator

PROTECTED:balance

It’s possible to create a new class that inherits from both the CreditAccount class and the DebitAccount class, but the fact that both inherit from the Account class makes such a move somewhat problematic...

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 99

/////////////////////////////////////////////////// Class definition file: DebitCreditAccount.h //// //// In this header file, a subclass of the //// CreditAccount class is defined to hold //// information about an account that is //// essentially both a DebitAccount and a //// CreditAccount. Inheriting members from //// the CreditAccount class, it only needs //// 3 additional members: an initializing //// constructor, a function to compound the //// daily interest on the account, and a data //// member representing a daily interest rate. ///////////////////////////////////////////////////#ifndef DEB_CRED_ACCT_H

#include "CreditAccount.h"class DebitCreditAccount : public CreditAccount{ public: // Class constructor DebitCreditAccount(float initialBalance, float intRate, float finChgRate); //Member function void compoundInterest();

protected: // Data member float dailyIntRate;};#define DEB_CRED_ACCT_H#endif

///////////////////////////////////////////// Class implementation file: //// DebitCreditAccount.cpp //// //// This program file contains the imple- //// mentation of the member function of //// the DebitCreditAccount subclass which //// inherits from the CreditAccount class //// and has additional characteristics of //// the DebitAccount class. /////////////////////////////////////////////#include "DebitCreditAccount.h"

// The DebitCreditAccount initializing //// constructor inherits from the Credit- //// Account initializing constructor, with //// the addition of an initializing assign- //// ment of the dailyIntRate data member. //DebitCreditAccount::DebitCreditAccount (float initialBalance, float intRate, float finChgRate): CreditAccount(initialBalance, finChgRate){ dailyIntRate = intRate; }

// The compoundInterest function updates a //// DebitCreditAccount's balance by taking //// the product of the incoming interest //// rate & the DebitCreditAccount's balance,//// and adding that product to the balance. //void DebitCreditAccount::compoundInterest(){ if (getBalance() > 0.0F) deposit(getBalance() * dailyIntRate);}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 1010

class DebitCreditAccount:public

CreditAccountPUBLIC:

compoundInterest

PROTECTED:dailyIntRate

withdrawapplyFinanceCharge

dailyFinChgRate

depositwithdraw

getBalance= operator

balance

class CreditAccount:public

AccountPUBLIC:withdraw

applyFinanceCharge

PROTECTED:dailyFinChgRate

depositwithdraw

getBalance= operator

balance

class Account

PUBLIC:deposit

withdrawgetBalance= operator

PROTECTED:balance

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 1111

//////////////////////////////////////////////////// Program file: DebitCreditDriver.cpp //// This program tests various aspects of the //// Account class and its three subclasses: //// DebitAccount, CreditAccount, and Debit- //// CreditAccount. ////////////////////////////////////////////////////#include <iostream.h>#include <iomanip.h>#include <fstream.h>#include "DebitAccount.h"#include "CreditAccount.h"#include "DebitCreditAccount.h"

void printBalance(const char name[], Account &a);

// The main function sets up three variables, //// one of type DebitAccount one of type Credit- //// Account, and one of type DebitCreditAccount. //// It then cycles through a month's banking //// transactions for each Account, comparing //// what the results would be if a person used //// two Accounts (an interest-generating Debit- //// Account in which funds are deposited and a //// finance-charge-generating CreditAccount from //// which money is removed when needed) versus //// if a person used a single DebitCreditAccount,//// which generates interest on those days when /// it has a positive balance and incurs a finance//// charge otherwise. Output messages indicating//// the initial and the final status of each //// Account are generated for a specific sample //// month. //

void main(){ DebitAccount deb(1000.00F, 0.0001F); CreditAccount cred(0.00F, 0.0005F); DebitCreditAccount deb_cred(1000.00F, 0.0001F, 0.0005F); // The next variable is a floating-point // value that represents a transaction for // the Accounts in question, with positive // numbers used for deposits and negative // numbers used for withdrawals. It is // assumed that a person using the two- // Account approach always applies three- //quarters of any deposited amount to the // CreditAccount, and the other quarter to // the DebitAccount. It is also assumed // that this person retrieves half of each // withdrawn amount from the CreditAccount, // and the other half from the Debit- // Account. float transaction;

ifstream inputFile; int nbrOfTransactions;

cout.setf(ios::fixed); cout << setprecision(2);

cout << "INITIAL STATUS OF ACCOUNTS\n"; printBalance("Debit: ", deb); printBalance("Credit: ", cred); printBalance("Debit-Credit: ", deb_cred);

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 1212

// This section of code loops through the // daily transactions for the three Accounts. inputFile.open("transactions.txt"); nbrOfTransactions = 0; inputFile >> transaction; while (!inputFile.eof()) { nbrOfTransactions++; if (transaction < 0.0F) { deb.withdraw(-0.5F * transaction); cred.withdraw(-0.5F * transaction); deb_cred.withdraw(-transaction); } else if (transaction > 0.0F) { deb.deposit(0.25F * transaction); cred.deposit(0.75F * transaction); deb_cred.deposit(transaction); } deb.compoundInterest(); cred.applyFinanceCharge(); deb_cred.compoundInterest(); deb_cred.applyFinanceCharge(); inputFile >> transaction; }

cout << endl << "FINAL STATUS OF ACCOUNTS\n"; printBalance("Debit: ", deb); printBalance("Credit: ", cred); printBalance("Debit-Credit: ", deb_cred); cout << endl; return;}

// Function printBalance outputs the //// current balance of the Account. Note //// that it can use an Account as its //// second parameter. //void printBalance(const char header[], Account &a){ cout << header << '$' << a.getBalance() << endl;}

200.00 0.00 0.00-100.00 0.00-160.00 -40.00-600.00 0.00 0.00 -80.00 0.00 0.00 0.00-600.00 0.00 400.00 0.00 0.00 0.00 200.00-800.00 0.00 0.00 200.00 0.00 0.00 0.00-120.00 500.00

Input File:transactions.txt

Resulting Output

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 1313

// Class declaration file: queue.h// Array implementation of the queue ADT.#ifndef QUEUE_H#include <fstream>using namespace std;

typedef int elementType;const MAX_QUEUE_SIZE = 10;

class Queue{ public: // Class constructors Queue(); Queue(const Queue &q); // Member functions bool isEmpty() const; void enqueue(const elementType &item); elementType dequeue(); void inputEnqueue(ifstream &input); friend ostream& operator << (ostream &destFile, const Queue &q); protected: // Data members int front, rear, length; elementType list[MAX_QUEUE_SIZE]; // Member function bool isFull() const;};

#define QUEUE_H#endif

// Class implementation file: Queue.cpp// Array implementation of the Queue ADT.

#include "Queue.h"#include <assert.h>

// Default constructor: Make empty Queue //Queue:: Queue(){ front = 0; rear = MAX_QUEUE_SIZE - 1; length = 0;}

// Copy constructor: Make copy of Queue. //Queue:: Queue(const Queue &q){ int index; front = q.front; rear = q.rear; length = q.length; for (int i = 0; i < length; i++) { index = (i + q.front) % MAX_QUEUE_SIZE; list[index] = q.list[index]; }}

Inheritance Example #2: Weeding QueuesInheritance Example #2: Weeding Queues

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 1414

// isEmpty function: signals if //// *this is an empty Queue. //bool Queue:: isEmpty() const{ return (length == 0);}

// Enqueue function; inserts a new //// item into the rear of Queue *this //// (if there's enough room). //void Queue:: enqueue(const elementType &item){ assert(!isFull()); rear = (rear+1) % MAX_QUEUE_SIZE; list[rear] = item; length++;}

// Dequeue function; remove the item //// at the front of Queue *this (if //// there’s one there). //elementType Queue:: dequeue(){ elementType item; assert(!isEmpty()); item = list[front]; front = (front+1) % MAX_QUEUE_SIZE; length--; return item;}

// InputEnqueue function: inputs items in //// param. file, enqueueing each into *this. //void Queue::inputEnqueue(ifstream &input){ elementType item; input >> item; while (!input.eof()) { enqueue(item); input >> item; } return;}

// Output operator: outputs Queue elts to //// parameterized output file, from front //// of Queue to rear, w/o removing items. //ostream& operator << (ostream &destFile, const Queue &q){ int index; for (int i = 0; i < q.length; i++) { index = (i + q.front) % MAX_QUEUE_SIZE; destFile << q.list[index] << endl; } return destFile;}

// isFull function; returns bool indicating //// if *this is a full Queue (wrt the array). //bool Queue:: isFull() const{ return (length == MAX_QUEUE_SIZE); }

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 1515

// Class declaration file: WeedingQueue.h// This subclass of the Queue class; // "weeds" out smaller values whenever // the structure is about to overflow.

#ifndef WEEDING_QUEUE_H

#include "Queue.h" using namespace std;class WeedingQueue: public Queue{ public: // Member function void enqueue(const elementType &item);};

#define WEEDING_QUEUE_H#endif

// Class implementation file:// WeedingQueue.cpp// This subclass of the Queue class; // "weeds" out smaller values whenever // the structure is about to overflow.#include "WeedingQueue.h"

// Enqueue function; inserts a new item //// in the rear of WeedingQueue *this (if //// there's enough room). If there isn’t //// enough room, the smallest element in //// the WeedingQueue is removed (even if //// it's not at the front of the Weeding- //// Queue), and then the new item is in- //// serted at the rear of the WeedingQueue.//

void WeedingQueue:: enqueue(const elementType &item){ int index;

if (isFull()) { // Locate the smallest element. int minIndex = 0; for (index = 1; index < length; index++) if (list[(front+index) % MAX_QUEUE_SIZE] < list[(front+minIndex) % MAX_QUEUE_SIZE]) minIndex = index;

// If the new item is smaller, don't insert it. if (item < list[(front+minIndex)%MAX_QUEUE_SIZE]) return;

// Otherwise, remove the smallest element. for (index = minIndex; index < length; index++) list[(front + index) % MAX_QUEUE_SIZE] = list[(front + index + 1) % MAX_QUEUE_SIZE]; length--; rear = (front + length - 1) % MAX_QUEUE_SIZE; }

// Now insert the new element. rear = (rear+1) % MAX_QUEUE_SIZE; list[rear] = item; length++;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 1616

// Program file: FirstQueueDriver.cpp //// This program tests the WeedingQueue //// class by inserting 50 values via //// direct input with an eof check. //

#include <iostream.h>#include <fstream.h>#include "WeedingQueue.h"

// The main function inputs and //// outputs a WeedingQueue. //void main(){ WeedingQueue wq; ifstream inputFile; elementType item; inputFile.open("queueData.txt"); inputFile >> item; while (!inputFile.eof()) { wq.enqueue(item); inputFile >> item; } cout << wq; return;}

33 56 82 90 47 10 94 36 89 2188 35 91 17 53 28 59 82 36 7216 38 78 92 73 16 83 95 19 6646 20 39 65 48 27 63 49 14 8462 31 93 38 77 80 11 98 67 45

Contents of queueData.txt

Resulting interactive session

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 1717

// Program file: SecondQueueDriver.cpp //// This program tests the WeedingQueue //// class by inserting 50 values via //// the inputEnqueue member function. //

#include <iostream.h>#include <fstream.h>#include "WeedingQueue.h"

// The main function inputs and //// outputs a WeedingQueue. //void main(){ WeedingQueue wq; ifstream inputFile; inputFile.open("queueData.txt"); wq.inputEnqueue(inputFile); cout << wq; return;}

33 56 82 90 47 10 94 36 89 2188 35 91 17 53 28 59 82 36 7216 38 78 92 73 16 83 95 19 6646 20 39 65 48 27 63 49 14 8462 31 93 38 77 80 11 98 67 45

Contents of queueData.txt

Resulting interactive session

Why Why did did this this

crash?crash?

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 1818

Virtual Functions and Late BindingVirtual Functions and Late BindingThe problem in the previous example relates to the fact The problem in the previous example relates to the fact that the WeedingQueue subclass used the that the WeedingQueue subclass used the inputEnqueue function that it inherited from the Queue inputEnqueue function that it inherited from the Queue class.class.

void Queue::inputEnqueue(ifstream &input){ elementType item; input >> item; while (!input.eof()) { enqueue(item); input >> item; } return;}

When the compiler When the compiler analyzes this code, it’s analyzes this code, it’s

doing it in the context of doing it in the context of the the QueueQueue class. class.

Consequently, it “binds” Consequently, it “binds” this line to the this line to the enqueueenqueue member function of the member function of the

QueueQueue class, not the class, not the enqueueenqueue member function member function

of the of the WeedingQueueWeedingQueue subclass!subclass!

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 1919

// Class declaration file: queue.h// Array implementation of the queue ADT.#ifndef QUEUE_H#include <fstream.h>

typedef int elementType;const MAX_QUEUE_SIZE = 10;

class Queue{ public: // Class constructors Queue(); Queue(const Queue &q); // Member functions bool isEmpty() const; virtual void enqueue(const elementType &item); elementType dequeue(); void inputEnqueue(ifstream &input); friend ostream& operator << (ostream &destFile, const Queue &q); protected: // Data members int front, rear, length; elementType list[MAX_QUEUE_SIZE]; // Member function bool isFull() const;};

#define QUEUE_H#endif

// Class declaration file: WeedingQueue.h// This subclass of the Queue class; // "weeds" out smaller values whenever // the structure is about to overflow.

#ifndef WEEDING_QUEUE_H#include "Queue.h"

class WeedingQueue: public Queue{ public: // Member function virtual void enqueue(const elementType &item);};

#define WEEDING_QUEUE_H#endif

To ensure that the To ensure that the correct context is correct context is used, declare each used, declare each version of enqueue version of enqueue

as a “virtual” as a “virtual” function.function.

Then binding won’t Then binding won’t occur until execution occur until execution

time! time!

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 2020

Notice that labeling the Notice that labeling the enqueue functions as enqueue functions as virtual did the trick!virtual did the trick!

Generally, follow these guidelines when Generally, follow these guidelines when deciding whether to make a member function deciding whether to make a member function virtual:virtual: Make the functions of the superclass virtual, Make the functions of the superclass virtual,

so they can be overridden.so they can be overridden.

Never make constructors virtual.Never make constructors virtual.

Always make destructors virtual.Always make destructors virtual.

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 2121

TemplatesTemplatesC++ provides a mechanism for avoiding redundancy in C++ provides a mechanism for avoiding redundancy in the creation of classes and functions.the creation of classes and functions.

Linked Linked List Class List Class for charfor char

Linked Linked List Class List Class for stackfor stack

Linked Linked List Class List Class for stringfor string

Linked Linked List Class List Class for doublefor double

Linked Linked List Class List Class

for for nodePtrnodePtr

Linked Linked List Class List Class for matrixfor matrix

Linked Linked List Class List Class for boolfor bool

Linked Linked List Class List Class for queuefor queue

Linked Linked List Class List Class for floatfor float

Linked Linked List Class List Class

for intfor int

Linked Linked List Class List Class

for for bankAcctbankAcct

Linked Linked List Class List Class for long for long

intint

Swap Swap Function Function for boolfor bool

Swap Swap Function Function

for for queuequeue

Swap Swap Function Function for charfor char

Swap Swap Function Function for stackfor stack Swap Swap

Function Function for floatfor float

Swap Swap Function Function

for intfor int

Swap Swap Function Function

for for matrixmatrix

Swap Swap Function Function for stringfor string

Swap Swap Function Function

for for doubledouble

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 2222

Class Template Example: The Two-Field Class Template Example: The Two-Field LabelLabel

field1

field2indent2

indent1

topGap

midGapheight

The two-field label The two-field label class template will class template will allow two values, allow two values, field1 and field2, to be field1 and field2, to be placed into a label placed into a label that can be output.that can be output.

It is assumed that the It is assumed that the types of fields1 and types of fields1 and fields2 have a member fields2 have a member function function getLineNumbergetLineNumber that takes an integer that takes an integer parameter and returns parameter and returns the corresponding line the corresponding line of the field, as well as of the field, as well as a member function a member function heightheight that returns that returns the number of output the number of output lines required by the lines required by the field.field.

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 2323

Definition & Implementation of the Two-Field Label ClassDefinition & Implementation of the Two-Field Label Class////////////////////////////////////////////////////// Class definition file: TwoFieldLabel.h //// //// This file defines the two-field label class of //// objects. Each two-field label contains two //// template-based fields that will be displayed //// in a rectangular region. This region will //// have a specified width and height, as well as //// an indentation for each field, a vertical gap //// between the fields, and a gap between the top //// of the rectangular region and the first field. //// An output operator is also specified for the //// two-field label. //////////////////////////////////////////////////////#ifndef TWO_FIELD_LABEL_H#include <iostream>

const int MIN_LABEL_HEIGHT = 3;

/*** DEFINITION SECTION ***/template <class E1, class E2> class twoFieldLabel{ public: // Constructors twoFieldLabel(); twoFieldLabel(int in1, int in2, int tg, int mg); twoFieldLabel(int h); twoFieldLabel(E1 f1, E2 f2); twoFieldLabel(const twoFieldLabel<E1, E2> &tfl);

// Member functions E1 getField1() const {return field1;} E2 getField2() const {return field2;} int getIndent1() const {return indent1;} int getIndent2() const {return indent2;} int getHeight() const {return height;} int getTopGap() const {return topGap;} int getMidGap() const {return midGap;}

void setField1(const E1 &fd1) {field1 = fd1;} void setField2(const E2 &fd2) {field2 = fd2;} void setIndent1(int in1) {indent1 = (in1 < 0) ? 0 : in1;} void setIndent2(int in2) {indent2 = (in2 < 0) ? 0 : in2;} void setHeight(int h) {height = (h < 0) ? 0 : h;} void setTopGap(int tg) {topGap = (tg < 0) ? 0 : tg;} void setMidGap(int mg) {midGap = (mg < 0) ? 0 : mg;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 2424

friend ostream& operator << (ostream &os, const twoFieldLabel<E1, E2> &tfl);

private: // Data members E1 field1; E2 field2; int indent1; int indent2; int height; int topGap; int midGap;};

/*** IMPLEMENTATION SECTION ***/

// Default constructor: Sets *this to //// have minimal height, gap sizes, and //// indentations, and no field values. //template <class E1, class E2>twoFieldLabel<E1, E2>::twoFieldLabel(){ height = MIN_LABEL_HEIGHT; indent1 = indent2 = topGap = 0; midGap = 1;}

// Initializing constructor: Sets *this to //// have the parameterized gap sizes and in- //// dentations, no field values, and minimal //// height to accommodate gap sizes. //template <class E1, class E2>twoFieldLabel<E1, E2>::twoFieldLabel(int in1, int in2, int tg, int mg){ indent1 = (in1 < 0) ? 0 : in1; indent2 = (in2 < 0) ? 0 : in2; topGap = (tg < 0) ? 0 : tg; midGap = (mg < 1) ? 1 : mg; height = topGap + midGap + 2;}

// Initializing constructor: Sets *this to //// have the parameterized gap sizes and in- //// dentations, no field values, and minimal //// height to accommodate gap sizes. //template <class E1, class E2>twoFieldLabel<E1, E2>::twoFieldLabel(int h){ height = h; indent1 = indent2 = topGap = 0; midGap = 1; height = (h < MIN_LABEL_HEIGHT) ? MIN_LABEL_HEIGHT : h;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 2525

// Initializing constructor: Sets *this to //// have the parameterized field values, //// minimal height to accommodate the fields, //// and minimal gap sizes and indentation. //template <class E1, class E2>twoFieldLabel<E1, E2>::twoFieldLabel(E1 f1, E2 f2){ height = f1.height() + f2.height() + 1; indent1 = indent2 = topGap = 0; midGap = 1; field1 = f1; field2 = f2;}

// Copy constructor: copies the field //// values, gap sizes, indentations and //// heights from the parameterized //// twoFaceLabel into *this. //template <class E1, class E2>twoFieldLabel<E1, E2>::twoFieldLabel

(const twoFieldLabel<E1, E2> &tfl){ height = tfl.getHeight(); indent1 = tfl.getIndent1(); indent2 = tfl.getIndent2(); topGap = tfl.getTopGap(); midGap = tfl.getMidGap(); field1 = tfl.getField1(); field2 = tfl.getField2();}

// The output operator is overloaded to ap- //// propriately format the two-field label. //

template <class E1, class E2>ostream& operator << (ostream &os, const twoFieldLabel<E1, E2> &tfl){ int i, j; int bottomGap = tfl.getHeight() - tfl.getTopGap() - tfl.getField1().height() - tfl.getMidGap() - tfl.getField2().height(); for (i = 1; i <= tfl.getTopGap(); i++) os << endl; for (i=1; i <= tfl.getField1().height(); i++) { for (j=1; j <= tfl.getIndent1(); j++) os << ' '; os << tfl.getField1().getLineNumber(i) << endl; } for (i=1; i <= tfl.getMidGap(); i++) os << endl; for (i=1; i <= tfl.getField2().height(); i++) { for (j=1; j <= tfl.getIndent2(); j++) os << ' '; os << tfl.getField2().getLineNumber(i) << endl; } for (i=1; i <= bottomGap; i++) os << endl; return os;}#define TWO_FIELD_LABEL_H#endif

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 2626

New New PersonPerson Class for Use in the Two-Field Label Class Class for Use in the Two-Field Label Class////////////////////////////////////////////////// Class implementation file: Person.h //// This program file contains the definitions //// of the members of the person class, which //// consists of three strings representing a //// person's name and address information. //////////////////////////////////////////////////#ifndef PERSON_H#include <string>using namespace std;const int NBR_OF_OUTPUT_LINES = 3;class person{ public: // Constructors person(); person(const person &p); person(string fnm, string ad1, string ad2); // Member functions int height(); string getLineNumber(int i); protected: // Data members string fullName; string firstAddressLine; string secondAddressLine;};#define PERSON_H#endif

///////////////////////////////////////////// Class implementation file: Person.cpp //// //// This program file contains the actual //// implementations of the member func- //// tions of the person class defined in //// the Person.h header file. /////////////////////////////////////////////#include "Person.h"#include <string>using namespace std;

// The default constructor sets the //// 3 data members to empty strings. //person::person(){ fullName = firstAddressLine = secondAddressLine = "";}

// The copy constructor sets the 3 data //// members to the corresponding data //// member values of the param. person. //person::person(const person &p){ fullName = p.fullName; firstAddressLine = p.firstAddressLine; secondAddressLine = p.secondAddressLine;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 2727

// The initializing constructor sets //// the three data members of *this to //// the parameterized string values. //person::person(string fnm, string ad1, string ad2){ fullName = fnm; firstAddressLine = ad1; secondAddressLine = ad2;}

// The height member function returns //// the number of output lines that are //// needed to output the person *this. //int person::height(){ return NBR_OF_OUTPUT_LINES;}

// The getLineNumber member function returns //// the appropriate addressing line, depending //// upon the value of the integer parameter. //string person::getLineNumber(int i){ switch (i) { case 3: return secondAddressLine; break; case 2: return firstAddressLine; break; default: return fullName; break; }}

Notice that the Notice that the personperson class has class has the required the required getLineNumbergetLineNumber & & heightheight member member functions.functions.

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 2828

New New MonetaryMonetary Class for Use in the Two-Field Label Class Class for Use in the Two-Field Label Class////////////////////////////////////////////// Class definition file: Monetary.h //// //// This program file contains the defini- //// tions of the members of the monetary //// class, which consists of a float value //// representing dollars and cents. //////////////////////////////////////////////#ifndef MONETARY_H#include <string>using namespace std;class monetary{ public: // Constructors monetary(); monetary(const float &amt); monetary(const monetary &m);

// Member functions int height(); string getLineNumber(int i);

protected: // Data member float amount;};#define MONETARY_H#endif

/////////////////////////////////////////////// Class implementation file: Monetary.cpp //// This program file contains the actual //// implementations of the member functions //// of the monetary class defined in the //// Monetary.h header file. ///////////////////////////////////////////////#include "Monetary.h"#include <string>using namespace std;

// The default constructor sets //// the monetary amount to zero. //monetary::monetary(){ amount = 0.00F;}

// The initializing constructor sets the //// monetary amount to the param. value. //monetary::monetary(const float &amt){ amount = amt;}

// The copy constructor sets the monetary //// amt to that of the param monetary value. //monetary::monetary(const monetary &m){ amount = m.amount;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 2929

// The height member function returns the number of output //// lines that are needed to output the monetary *this. //int monetary::height(){ return 1;}

// The getLineNumber member function converts the monetary's amount into //// a string corresponding to the appropriate amount of dollars and cents. //string monetary::getLineNumber(int i){ string s = "$"; string reverseDollarText = ""; int dollars = (int)amount; int cents = (int)(100 * (amount - dollars)); int digit; if (dollars == 0) s += '0'; else { while (dollars > 0) { digit = dollars % 10; dollars /= 10; reverseDollarText += ('0' + digit); } for (i = reverseDollarText.length() - 1; i >= 0; i--) s += (reverseDollarText[i]); } s += '.'; s += ('0' + (cents / 10)); s += ('0' + (cents % 10)); return s;}

Notice that the Notice that the monetarymonetary class class has the has the required required getLineNumbergetLineNumber & & heightheight member member functions.functions.

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 3030

New New LabelStringLabelString Class for Use in the Two-Field Label Class Class for Use in the Two-Field Label Class//////////////////////////////////////////// Class definition file: LabelString.h //// //// This program file contains the defi- //// nitions of the members of the label- //// String class,which consists of a //// single string value. ////////////////////////////////////////////#ifndef LABEL_STRING_H#include <string>using namespace std;

class labelString{ public: // Constructors labelString(); labelString(const char str[]); labelString(const string &str); labelString(const labelString &ls); // Member functions int height(); string getLineNumber(int i);

protected: // Data member string text;};

#define LABEL_STRING_H#endif

////////////////////////////////////////////////// Class implementation file: LabelString.cpp //// This program file contains the actual im- //// plementations of the member functions of //// the labelString class defined in the //// LabelString.h header file. //////////////////////////////////////////////////#include <string>#include "LabelString.h"using namespace std;

// The copy constructor sets the labelString's //// text data member to an empty string. //labelString::labelString(){ text = "";}

// This initializing constructor sets the text //// data member to the param. character array. //labelString::labelString(const char str[]){ text = str;}

// This initializing constructor sets the text //// data member to the param. string value. //labelString::labelString(const string &str){ text = str;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 3131

// The copy constructor sets the *this label- //// String's text data member to the parameter- //// ized labelString's text data member. //labelString::labelString(const labelString &ls){ text = ls.text;}

// The height member function returns the //// number of output lines that are needed //// to output the labelString *this. //int labelString::height(){ return 1;}

// The getLineNumber member function disregards //// the integer parameter and merely retrieves //// the text data member of the *this labelString. //string labelString::getLineNumber(int i){ return text;}

Notice that the Notice that the labelStringlabelString class has the class has the required required getLineNumbergetLineNumber & & heightheight member member functions.functions.

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 3232

Driver Using a Two-Field Label with Two Driver Using a Two-Field Label with Two PersonPerson Fields Fields/////////////////////////////////////////////////////////////////////// Program file: MailingLabelDriver.cpp //// //// This driver program retrieves destination addresses for several //// customers from an external file, and then generates an output //// file of mailing labels for these items, using a user-supplied //// source address and the retrieved destination addresses. ///////////////////////////////////////////////////////////////////////#include "Person.h"#include "TwoFieldLabel.h"#include <iostream>#include <string>#include <fstream>using namespace std;

const int MAX_STRING_SIZE = 40;const int MAX_FILENAME_SIZE = 80;const int RTRN_ADDR_INDENT = 2;const int DEST_ADDR_INDENT = 25;const int TOP_GAP = 2;const int MIDDLE_GAP = 8;const int LABEL_HEIGHT = 20;

void queryUser(person &p, char inputFileName[], char outputFileName[]);void createLabels(person source, ifstream &personFile, ofstream &labelFile);twoFieldLabel<person, person> generateLabel(const person &source, const person &destination);

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 3333

// The main function queries the user for source & destination //// info, and generates the output file of mailing labels. //void main(){ person source; char personFileName[MAX_FILENAME_SIZE]; char labelFileName[MAX_FILENAME_SIZE]; ifstream personFile; ofstream labelFile;

queryUser(source, personFileName, labelFileName); personFile.open(personFileName); labelFile.open(labelFileName); createLabels(source, personFile, labelFile); personFile.close(); labelFile.close(); return;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 3434

// Function queryUser queries the user for the source person info, the name of //// the input file containing the data regarding each destination person, and //// the name of the output file for the labels that are being generated. //void queryUser(person &p, char inputFileName[], char outputFileName[]){ char name[MAX_STRING_SIZE], addr[MAX_STRING_SIZE], site[MAX_STRING_SIZE];

cout << "Enter the full name of the sender: "; cin.getline(name, MAX_STRING_SIZE); while string(name) == "") cin.getline(name, MAX_STRING_SIZE);

cout << "Enter the street address of the sender: "; cin.getline(addr, MAX_STRING_SIZE); while (string(addr) == "") cin.getline(addr, MAX_STRING_SIZE);

cout << "Enter the city, state, and zip code of the sender: "; cin.getline(site, MAX_STRING_SIZE); while (string(site) == "") cin.getline(site, MAX_STRING_SIZE);

p = person(name, addr, site); cout << "Enter the name of the file where the destination addresses reside: "; cin >> inputFileName; cout << "Enter the name of the file where the mailing labels should be placed: "; cin >> outputFileName; cout << endl << endl;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 3535

// The createLabels function reads all of the person data from the input file, //// and generates a mailing label to each person, with the source parameter as //// the return address. Each label is then written to the output file. //void createLabels(person source, ifstream &personFile, ofstream &labelFile){ twoFieldLabel<person, person> label; person destination; char name[MAX_STRING_SIZE], addr[MAX_STRING_SIZE], site[MAX_STRING_SIZE]; personFile.getline(name, MAX_STRING_SIZE); while ((string(name) == "") && !personFile.eof()) personFile.getline(name, MAX_STRING_SIZE); while (!personFile.eof()) { personFile.getline(addr, MAX_STRING_SIZE); while (string(addr) == "") personFile.getline(addr, MAX_STRING_SIZE); personFile.getline(site, MAX_STRING_SIZE); while (string(site) == "") personFile.getline(site, MAX_STRING_SIZE); destination = person(name, addr, site); label = generateLabel(source, destination); labelFile << label << endl; for (int i = 1; i <= DEST_ADDR_INDENT+MAX_STRING_SIZE; i++) labelFile << '-'; personFile.getline(name, MAX_STRING_SIZE); while ((string(name) == "") && !personFile.eof()) personFile.getline(name, MAX_STRING_SIZE); }}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 3636

// Function generateLabel produces the two-field //// label that will serve as a mailing label. //twoFieldLabel<person, person> generateLabel(const person &source,

const person &destination){ twoFieldLabel<person, person> label(RTRN_ADDR_INDENT, DEST_ADDR_INDENT, TOP_GAP, MIDDLE_GAP); label.setHeight(LABEL_HEIGHT); label.setField1(source); label.setField2(destination); return label;}

Darth Vader 666 Imperial Lane Coruscant, CA 90210

Fred Flintstone One Million BC Lane Bedrock CA 00000

-----------------------------------------------------------------

Darth Vader 666 Imperial Lane Coruscant, CA 90210

Marge Simpson 417 Evergreen Street Springfield IL 36963

-----------------------------------------------------------------

Darth Vader 666 Imperial Lane Coruscant, CA 90210 ...

LBL.txtLBL.txt

Fred FlintstoneOne Million BC LaneBedrock CA 00000

Marge Simpson417 Evergreen StreetSpringfield IL 36963

Ren Hoek1237 Stimpy AvenueMudskipper WI 86420

Scooby Doo666 Shaggy DriveAmityville MA 75421

...

Addresses.txtAddresses.txt

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 3737

Driver Using a Two-Field Label w/ Driver Using a Two-Field Label w/ LabelStringLabelString & & MonetaryMonetary FieldsFields

///////////////////////////////////////////////////////////////////////////// Program file: PriceTagDriver.cpp //// This driver program retrieves inventory numbers, prices, and amounts //// for several items of merchandise from an interactive session with the //// user, and then generates a file of price tag labels for these items. /////////////////////////////////////////////////////////////////////////////

#include "Monetary.h“#include "LabelString.h"#include "TwoFieldLabel.h"#include <iostream>#include <fstream>

bool queryUser(labelString &ls, monetary &m, int &inventorySize, char outputFileName[]);twoFieldLabel<labelString, monetary> generateLabel(const labelString &ls, const monetary &m);

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 3838

// The main function repeatedly asks the user whether or not to //// generate more price tags, and generates them in the user-specified //// destination files until the user says to stop. //void main(){ twoFieldLabel<labelString, monetary> label; labelString itemNumber; monetary itemPrice; int itemInventorySize; char labelFileName[80]; ofstream labelFile;

while (queryUser(itemNumber, itemPrice, itemInventorySize, labelFileName)) { labelFile.open(labelFileName); label = generateLabel(itemNumber, itemPrice); for (int i = 1; i <= itemInventorySize; i++) labelFile << label << "***************" << endl;; labelFile.close(); } return;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 3939

// Function queryUser queries the user for the inventory number, price, amt. //// of stock, and output file name for the labels that are being generated. //bool queryUser(labelString &ls, monetary &m, int &inventorySize, char outputFileName[]){ char YorN; string invNbr; float price;

cout << endl << "Would you like to generate some price tags? (Enter Y or N:) "; cin >> YorN; if ((YorN == 'y') || (YorN == 'Y')) { cout << "Please enter the inventory number: "; cin >> invNbr; ls = invNbr; cout << "Please enter the price of the item in question: $"; cin >> price; m = price; cout << "Please enter the number of price tags you wish to produce: "; cin >> inventorySize; cout << "Please enter the name of the file " << "where the price tags should be placed: "; cin >> outputFileName; return true; } else return false;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 4040

// Function generateLabel produces the two-field //// label that will serve as a price tag. //twoFieldLabel<labelString, monetary> generateLabel (const labelString &ls, const monetary &m){ twoFieldLabel<labelString, monetary> label(5); label.setField1(ls); label.setField2(m); return label;}

XYZ-123

$14.94

***************

XYZ-123

$14.94

***************

XYZ-123

$14.94

***************

ABC-789

$511.07

***************

ABC-789

$511.07

***************

ABC-789

$511.07

***************

ABC-789

$511.07

***************

ABC-789

$511.07

***************

XYZ.txt ABC.txt

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 4141

Driver Using a Two-Field Label with Driver Using a Two-Field Label with LabelStringLabelString & & PersonPerson FieldsFields/////////////////////////////////////////////////////////////////////

// Program file: PersonnelFileDriver.cpp //// //// This driver program retrieves personnel information (SSN, name, //// department number, mailstop) from an external file, and then //// generates an output file of folder labels for these employees, //// alternating between three different indentations. ///////////////////////////////////////////////////////////////////////#include "Person.h"#include "TwoFieldLabel.h"#include "LabelString.h"#include <iostream>#include <string>#include <fstream>

using namespace std;

const int MAX_STRING_SIZE = 20;const int MAX_FILENAME_SIZE = 40;const int NBR_LABEL_STYLES = 4;

void queryUser(char inputFileName[], char outputFileName[]);void generateLabelFile(ifstream &employeeFile, ofstream &labelFile);twoFieldLabel<labelString, person> generateLabel(const labelString &ssn, const person &employee);

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 4242

// The main function opens the I/O files, retrieves the employee data //// from the input file, and generates the output file of labels. //void main(){ char employeeFileName[MAX_FILENAME_SIZE]; char labelFileName[MAX_FILENAME_SIZE]; ifstream employeeFile; ofstream labelFile;

queryUser(employeeFileName, labelFileName); employeeFile.open(employeeFileName); labelFile.open(labelFileName); generateLabelFile(employeeFile, labelFile); employeeFile.close(); labelFile.close(); return;}

// Function queryUser queries the user for the names of the input file contain- //// ing the employee data and the output file for the labels being generated. //void queryUser(char inputFileName[], char outputFileName[]){ cout << "Enter the name of the file containing the employee information: "; cin >> inputFileName; cout << "Enter the name of the file where the “ << "personnel folder labels should go: "; cin >> outputFileName; cout << endl << endl;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 4343

// The generateLabelFile function reads the person data from //// the parameterized input file, & generates the folder labels //// that are written to the parameterized output file. //void generateLabelFile(ifstream &employeeFile, ofstream &labelFile){ twoFieldLabel<labelString, person> label; labelString labelSSN; string ssn; char name[MAX_STRING_SIZE], dept[MAX_STRING_SIZE], mail[MAX_STRING_SIZE]; person employee; int indent = 0; int separatorLength = NBR_LABEL_STYLES * MAX_STRING_SIZE;

employeeFile >> ssn; while (!employeeFile.eof()) { labelSSN = labelString(ssn); employeeFile.getline(name, MAX_STRING_SIZE); while (string(name) == "") employeeFile.getline(name, MAX_STRING_SIZE);

employeeFile.getline(dept, MAX_STRING_SIZE); while (string(dept) == "") employeeFile.getline(dept, MAX_STRING_SIZE);

employeeFile.getline(mail, MAX_STRING_SIZE); while (string(mail) == "") employeeFile.getline(mail, MAX_STRING_SIZE);

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 4444

employee = person(name, dept, mail); label = generateLabel(labelSSN, employee); label.setIndent1(indent); label.setIndent2(indent);

labelFile << label << endl;

for (int i = 1; i <= separatorLength; i++) labelFile << '+'; labelFile << endl; indent = (indent + MAX_STRING_SIZE) % separatorLength; employeeFile >> ssn; }}

// Function generateLabel produces the two-field label //// that will serve as a personnel folder label. //twoFieldLabel<labelString, person> generateLabel(const labelString &ssn, const person &employee){ twoFieldLabel<labelString, person> label(ssn, employee); return label;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 4545

223-66-9032Elroy JetsonDept. 63BMailstop 5031

221-80-9076Lisa SimpsonDept. 12CMailstop 1654

177-72-7874Harley QuinnDept. 33BMailstop 920

223-43-8190Scrappy DooDept. 71AMailstop 1902

222-22-2222Harvey DentDept. 22BMailstop 2222

220-53-8068Wile E. CoyoteDept. 43DMailstop 3117

221-91-0253Maggie SimpsonDept. 12CMailstop 1655

127-55-7293Pebbles FlintstoneDept. 33AMailstop 2825

637-44-1099Daisy DuckDept. 18CMailstop 3101

634-29-2906Minnie MouseDept. 18BMailstop 3096

224-64-1457Betty RubbleDept. 41DMailstop 1782

772-25-2765Quick Draw McGrawDept. 86XMailstop 3210

223-66-9032

Elroy JetsonDept. 63BMailstop 5031

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 221-80-9076

Lisa Simpson Dept. 12C Mailstop 1654

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 177-72-7874

Harley Quinn Dept. 33B Mailstop 920

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 223-43-8190

Scrappy Doo Dept. 71A Mailstop 1902

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++222-22-2222

Harvey DentDept. 22BMailstop 2222

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 220-53-8068

Wile E. Coyote Dept. 43D Mailstop 3117

++++++++++++++++++++++++++++++++++++++

employees.txtemployees.txt

FLDR.txtFLDR.txt

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 4646

Overloaded OperatorsOverloaded OperatorsAs we’ve seen, when we create a new class, we can overload As we’ve seen, when we create a new class, we can overload many of the operators that we’re accustomed to using with many of the operators that we’re accustomed to using with other C++ classes.other C++ classes.///////////////////////////////////////////

// Class Definition File: date.h //// The class definition file for the //// Date class, including the definition //// of the DayOfWeek enumerated type. /////////////////////////////////////////////#ifndef DATE_H#include <fstream>using namespace std;class Date{ public: Date(); Date(int m, int d, int y); bool setDate(int m, int d, int y); int getMonth() const; int getDay() const; int getYear() const;

bool operator == (const Date &d) const; bool operator != (const Date &d) const; bool operator < (const Date &d) const; bool operator <= (const Date &d) const; bool operator > (const Date &d) const; bool operator >= (const Date &d) const;

friend ostream& operator << (ostream &file, const Date &d);

private: int month; int day; int year;};

#define DATE_H#endif

OverloadedOverloadedEquality & InequalityEquality & Inequality

OperatorsOperators

OverloadedOverloadedOutputOutput

OperatorOperator

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 4747

////////////////////////////////////////////// Class Implementation File: date.cpp //// //// The class implementation file for the //// Date class, used to hold calendar date //// information and to calculate the day //// of the week for a particular date, to //// determine if the date is a weekday or //// part of a weekend, and to figure out //// if the date is a national holiday. //////////////////////////////////////////////

#include "date.h"#include <ctime>#include <iomanip>#include <fstream>using namespace std;

// The default constructor for the Date //// class sets *this to today's month, //// day, and year (as calculated via the //// functions in time.h). //Date::Date(){ struct tm *newtime; long int t; time( &t ); newtime = localtime( &t ); month = (newtime->tm_mon) + 1; day = (newtime->tm_mday); year = (newtime->tm_year) + 1900;}

// The initializing constructor for the Date //// class initializes *this with the parameter- //// ized values if they are legitimate calendar //// date values; if not, it sets *this to //// today's month, day, and year (as calculated //// via the functions in time.h). //Date::Date(int m, int d, int y){ bool validDate = false; switch (m) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: { validDate = ((d>=1) && (d<=31)); break; } case 4: case 6: case 9: case 11: { validDate = ((d>=1) && (d<=30)); break; } case 2: { if ((y%4==0) && ((y%100!=0) || (y%400==0))) validDate = ((d>=1)&&(d<=29)); else validDate = ((d>=1)&&(d<=28)); break; } } if (validDate) { month = m; day = d; year = y; }

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 4848

else { struct tm *newtime; long int t; time( &t ); newtime = localtime( &t ); month = (newtime->tm_mon) + 1; day = (newtime->tm_mday); year = (newtime->tm_year) + 1900; }}

// The setDate member function uses the //// initializing constructor to set *this //// to the parameterized Date values if //// they represent a legitimate calendar //// date; otherwise, the initializing //// constructor will set *this to today's //// date. //bool Date::setDate(int m, int d, int y){ Date dt(m, d, y); month = dt.getMonth(); day = dt.getDay(); year = dt.getYear(); return ((month == m) && (day == d) && (year == y));}

// The getMonth member function accesses //// the month data member of *this. //int Date::getMonth() const{ return month; }

// The getDay member function accesses //// the day data member of *this. //int Date::getDay() const{ return day; }

// The getYear member function accesses //// the year data member of *this. //int Date::getYear() const{ return year; }

// The equality operator for Dates: it verifies //// whether all 3 data members are identical. //bool Date::operator == (const Date &d) const{ return ((month == d.month) && (day == d.day) && (year == d.year));}

// The inequality operator for Dates: it //// verifies whether at least one of the //// three data members is not identical. //bool Date::operator != (const Date &d) const{ return !(*this == d);}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 4949

// The less-than operator for Dates: it //// verifies how the year values differ. If //// they don't, it verifies how the month //// values differ. If neither the years //// values nor the month values differ, it //// verifies how the day values differ. //bool Date::operator < (const Date &d) const{ return ((year < d.year) || ((year==d.year)&&(month<d.month)) || ((year==d.year) && (month==d.month) && (day < d.day)));}

// The less-than-or-equal operator for //// Dates: it verifies if the Dates are //// in ascending order. //bool Date::operator <= (const Date &d) const{ return ((*this == d) || (*this < d));}

// The greater-than operator for Dates: it //// verifies whether the less-than operator //// holds true if the operands are reversed. // bool Date::operator > (const Date &d) const{ return (d < *this);}

// The greater-than-or-equal operator for //// Dates: it verifies if the Dates are in //// descending order. //bool Date::operator >= (const Date &d) const{ return (d < = *this);}

// The output operator for Dates: it //// outputs the Date's data members, //// separated by forward slashes. //ostream& operator << (ostream &file, const Date &d){ file << setw(2) << d.getMonth() << '/' << setw(2) << d.getDay() << '/' << d.getYear(); return file;}

Note how Note how previously defined previously defined operators can be operators can be

used to implement used to implement additional additional operatorsoperators

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 5050

Function TemplatesFunction TemplatesJust like we did with class templates, we can employ function Just like we did with class templates, we can employ function templates to manipulate distinct classes in a similar fashion.templates to manipulate distinct classes in a similar fashion.

///////////////////////////////////////////////////////////// Program file: SalesDistribution.cpp //// This program uses reads sales data (dates, times, and //// amounts for various sales) into a trio of arrays. //// Using function templates, it then sorts and outputs //// the data to three different files, based upon type of //// data that was used as the sorting key. /////////////////////////////////////////////////////////////#include <iostream>#include <iomanip>#include <fstream>#include "date.h"using namespace std;

const int MAX_LIST_SIZE = 50;const int STD_OUTPUT_SIZE = 10;

void loadData(Date salesDate[], int salesTime[], float salesAmount[], int &listSize);

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 5151

template<class E>void showDistribution(char filename[], E list[], int size, char label[]);

template<class E>void selectionSort(E list[], int size);

template<class E>void swap(E &valueA, E &valueB);

template<class E>int indexOfSmallest(E list[], int startIndex, int stopIndex);

// The main function supervises the input and the //// sorting and output operations that transpire. //void main(){ Date dateList[MAX_LIST_SIZE]; int timeList[MAX_LIST_SIZE]; float amountList[MAX_LIST_SIZE]; int inputSize; ofstream outputFile;

loadData(dateList, timeList, amountList, inputSize); showDistribution("DistByDate.txt", dateList, inputSize, "date"); showDistribution("DistByTime.txt", timeList, inputSize, "time"); showDistribution("DistByAmnt.txt", amountList, inputSize, "amount"); return;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 5252

// The loadDate function loads the 3 arrays from a hard-coded //// input file. Data is assumed to be in the form: M D Y T A, //// where M is an integer month, D is an integer day, Y is an //// integer year, T is an integer time (military), and A is a //// floating-point amount (dollars & cents). //void loadData(Date salesDate[], int salesTime[], float salesAmount[], int &listSize){ int month, day, year; ifstream inputFile; inputFile.open("sales.txt"); listSize = 0; inputFile >> month; while (!inputFile.eof()) { inputFile >> day >> year; salesDate[listSize] = Date(month, day, year); inputFile >> salesTime[listSize]; inputFile >> salesAmount[listSize]; listSize++; inputFile >> month; } inputFile.close();}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 5353

// The showDistribution function template opens the output file with the //// parameterized name, outputs a header (using the parameterized label), //// and then sorts and outputs the parameterized list. //template<class E>void showDistribution(char filename[], E list[], int size, char label[]){ ofstream file; file.open(filename); file.setf(ios::fixed); file.precision(2); file << "Sales Distribution" << endl << " (by " << label << ")" << endl; selectionSort(list, size); for (int i = 0; i < size; i++) file << setw(STD_OUTPUT_SIZE) << list[i] << endl; file.close();}// The selectionSort function template sorts the parameterized list by //// repeatedly swapping the smallest unsorted element with the earliest one. // template<class E>void selectionSort(E list[], int size){ int smallestIndex; for (int i = 0; i < size - 1; i++) { smallestIndex = indexOfSmallest(list, i, size - 1); if (i != smallestIndex) swap(list[i], list[smallestIndex]); }}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 5454

// The swap function template merely swaps the values of //// the two parameters. It assumes that the assignment //// operator is defined for the E class. //template<class E>void swap(E &valueA, E &valueB){ E temp = valueA; valueA = valueB; valueB = temp; return;}

// The indexOfSmallest function template determines //// the index (between the two parameterized indices) //// of the smallest value in the parameterized list. //// It assumes that the less-than operator (<) has //// been defined for the class E. //template<class E>int indexOfSmallest(E list[], int startIndex, int stopIndex){ int smallestIndex = startIndex; for (int i = startIndex + 1; i <= stopIndex; i++) if (list[i] < list[smallestIndex]) smallestIndex = i; return smallestIndex;}

CS 240CS 240 Chapter 8 – Class Chapter 8 – Class RelationshipsRelationships

Page Page 5555

7 20 1999 1435 25.75 6 11 1998 922 216.63 1 9 2000 1114 75.80 4 20 1998 2012 407.4812 30 1998 1457 783.99 5 9 2000 1303 16.25 9 13 2000 1638 56.7310 16 1999 859 277.11 9 13 2000 1737 89.04 5 17 1999 1035 313.36 3 22 1998 1644 124.07 9 13 2000 905 90.15 7 20 2000 1833 35.12 6 11 1998 958 126.84 4 9 2000 1239 9.3611 20 1999 1904 15.3512 11 1998 921 117.77 8 9 2000 1706 23.92 9 11 1998 845 277.11 2 29 2000 2107 166.88

Sales Distribution (by date) 3/22/1998 4/20/1998 6/11/1998 6/11/1998 9/11/199812/11/199812/30/1998 5/17/1999 7/20/199910/16/199911/20/1999 1/ 9/2000 2/29/2000 4/ 9/2000 5/ 9/2000 7/20/2000 8/ 9/2000 9/13/2000 9/13/2000 9/13/2000

Sales Distribution (by time) 845 859 905 921 922 958 1035 1114 1239 1303 1435 1457 1638 1644 1706 1737 1833 1904 2012 2107

Sales Distribution (by amount) 9.36 15.35 16.25 23.92 25.75 35.12 56.73 75.80 89.04 90.15 117.77 124.07 126.84 166.88 216.63 277.11 277.11 313.36 407.48 783.99