SOLUTIONS ■ 559 // // city.h : Defines the CityCar class // #ifndef _CITY_H_ #define _CITY_H_ #include "car.h" class CityCar { private: Car* vp[100]; int cnt; public: CityCar(){ cnt = 0;} ~CityCar(); bool insert(const string& tp, bool sr, long n, const string& prod); bool insert(int a, double t, long n, const string& prod); void display() const; }; #endif // _CITY_H // // city.cpp : Methods of class CityCar // #include "city.h" CityCar::~CityCar() { for(int i=0; i < cnt; ++i) delete vp[i]; } // Insert a passenger car: bool CityCar::insert(const string& tp, bool sr, long n, const string& prod) { if( cnt < 100) { vp[cnt++] = new PassCar( tp, sr, n, prod); return true; } else return false; } 560 ■ CHAPTER 25 POLYMORPHISM // Insert a truck: bool CityCar::insert( int a, double t, long n, const string& prod) { if( cnt < 100) { vp[cnt++] = new Truck( a, t, n, prod); return true; } else return false; } void CityCar::display() const { cin.sync(); cin.clear(); // No previous input for(int i=0; i < cnt; ++i) { vp[i]->display(); if((i+1)%4 == 0) cin.get(); } } // // city_t.cpp : Test the CityCar class // #include "city.h" char menu(void); void getPassCar(string&, bool&, long&, string&); void getTruck(int&, double&, long&, string&); int main() { CityCar carExpress; string tp, prod; bool sr; int a; long n; double t; // Two cars are already present: carExpress.insert(6, 9.5, 54321, "Ford"); carExpress.insert("A-class", true, 54320, "Mercedes"); char choice; do { choice = menu(); switch( choice ) { case 'Q': case 'q': cout << "Bye Bye!" << endl; break; SOLUTIONS ■ 561 case 'P': case 'p': getPassCar(tp, sr, n, prod); carExpress.insert(tp, sr, n, prod ); break; case 'T': case 't': getTruck(a, t, n, prod); carExpress.insert(a, t, n, prod); break; case 'D': case 'd': carExpress.display(); cin.get(); break; default: cout << "\a"; // Beep break; } }while( choice != 'Q' && choice != 'q'); return 0; } char menu() // Input a command. { cout << "\n * * * Car Rental Management * * *\n\n" char c; cout << "\n P = Add a passenger car " << "\n T = Add a truck " << "\n D = Display all cars " << "\n Q = Quit the program " << "\n\nYour choice: "; cin >> c; return c; } void getPassCar(string& tp, bool& sr, long& n,string& prod) { char c; cin.sync(); cin.clear(); cout << "\nEnter data for passenger car:" << endl; cout << "Car type: "; getline(cin, tp); cout << "Sun roof (y/n): "; cin >> c; if(c == 'y' || c == 'Y') sr = true; else sr = false; cout << "Car number: "; cin >> n; cin.sync(); cout << "Producer: "; getline(cin, prod); cin.sync(); cin.clear(); } 562 ■ CHAPTER 25 POLYMORPHISM void getTruck(int& a, double& t, long& n, string& prod) { cout << "\nInput data for truck:" << endl; cout << "Number of axles: "; cin >> a; cout << "Weight in tons: "; cin >> t; cout << "Car number: "; cin >> n; cin.sync(); cout << "Producer: "; getline(cin, prod); cin.sync(); } Exercise 2 // // product.h : Defining the classes // Product, PrepackedFood, and FreshFood // // . . . class Product { private: long bar; string name; public: Product(long b = 0L, const string& s = "") : bar(b), name(s) { } // Access methods as previously used. virtual void scanner(); // Virtual now! virtual void printer() const; }; // The classes PrepackedFood and FreshFood are unchanged! // Refer to the solutions in Chapter 23. SOLUTIONS ■ 563 // // counter.cpp : Simulates a checkout desk // #include "product.h" void record(); int main() { cout << "\nHere is a checkout desk!" << endl; char c; while(true) { cin.sync(); cout << "\nAnother customer (y/n)? "; cin >> c; if(c == 'y' || c == 'Y') record(); else break; } return 0; } // // record() : Records the articles bought by a customer // and the total price. void record() { Product* v[100]; int x, i, cnt = 0; double sum = 0.0; for (i = 0; i < 100; i++) { cin.sync(); cout << "\nWhat is the next article?" << endl; cout << " 0 = No more article\n" << " 1 = Fresh Food\n" << " 2 = Prepacked article\n" << "? " ; cin >> x; if( x <= 0 || x >= 3) break; 564 ■ CHAPTER 25 POLYMORPHISM switch(x) { case 2: v[i] = new PrepackedFood; v[i]->scanner(); sum += ((PrepackedFood*)v[i])->getPrice(); break; case 1: v[i] = new FreshFood; v[i]->scanner(); sum += ((FreshFood*)v[i])->getPrice() * ((FreshFood*)v[i])->getWght(); break; } } cnt = i; for( i=0; i < cnt; i++) // Output v[i]->printer(); cout << "\n " << fixed << setprecision(2) << "\nTotal price: " << sum << endl; } 565 Abstract Classes This chapter describes how abstract classes can be created by defining pure virtual methods and how you can use abstract classes as a polymorphic interface for derived classes.To illustrate this we will be implementing an inhomogeneous list, that is, a linked list whose elements can be of various class types. chapter 26 566 ■ CHAPTER 26 ABSTRACT CLASSES // Coworker.h: Defining the abstract class Coworker. // #ifndef _COWORKER_H #define _COWORKER_H #include <string> #include <iostream> using namespace std; class Coworker { private: string name; // more information public: Coworker( const string& s = ""){ name = s; } virtual ~Coworker() {} // Destructor const string& getName() const{ return name; } void setName( const string& n){ name = n; } virtual void display() const; virtual double income() const = 0; virtual Coworker& operator=(const Coworker&); }; #endif The virtual operator function for the assignment will be described in the section on ”Virtual Assignments.” ✓ NOTE ■ PURE VIRTUAL METHODS The base class Coworker PURE VIRTUAL METHODS ■ 567 ᮀ Motivation Virtual methods are declared in the base class to ensure that they are available in any derived classes via the common class interface. It may happen that they rarely perform any useful tasks in the base class. For example, a destructor in a base class does not need to perform any explicit cleaning-up operations. In this case, of course, you can define a virtual dummy method whose address is entered in the VMT of the base class. However, this creates op-code for a function that should never be called. It makes more sense not to define a function like this. And this is where C++ steps in and gives you the opportunity of declaring pure virtual methods. ᮀ Declaration When a pure virtual method is declared, the method is identified by adding the expres- sion = 0. Example: virtual void demo()=0; // pure virtual This informs the compiler that there is no definition of the demo() method in the class. A NULL pointer is then entered in the virtual method table for the pure virtual method. ᮀ The Base Class Coworker The opposite page shows a definition of the Coworker class, which was designed to rep- resent human resources data for a company. The class is used as a base class for various employees, blue-collar, white-collar, and freelancers. To keep things simple the Coworker class has only a name as a data member. How- ever, it could also contain the address of an employee, or the division where the employee works. The Coworker class does not comprise data members to represent an employee’s salary. It makes more sense to store data like this in derived classes where the hourly wage and number of hours worked by a blue-collar worker and the monthly salary for a white-collar worker are also defined. The income() method is therefore not defined for the base class and can be declared as a pure virtual method. 568 ■ CHAPTER 26 ABSTRACT CLASSES // coworker.h: Extending the headerfile. // class Laborer : public Coworker { private: double wages; // Pay per hour int hr; public: Laborer(const string& s="", double w=0.0, int h=0) : Coworker(s), wages(w), hr(h){ } double getWages() const { return wages; } void setWages( double w ){ wages = w; } int getHr() const { return hr; } void setHr(int h ) { hr = h; } void display() const; double income() const; Laborer& operator=(const Coworker&); Laborer& operator=(const Laborer&); }; The operator functions for the assignments are discussed in the section ”Virtual Assignments.” ✓ NOTE ■ ABSTRACT AND CONCRETE CLASSES The derived class Laborer . class interface. It may happen that they rarely perform any useful tasks in the base class. For example, a destructor in a base class does not need to perform any explicit cleaning-up operations. In. menu(void); void getPassCar(string&, bool&, long&, string&); void getTruck(int&, double&, long&, string&); int main() { CityCar carExpress; string tp, prod; bool sr; int a; long. VIRTUAL METHODS The base class Coworker PURE VIRTUAL METHODS ■ 567 ᮀ Motivation Virtual methods are declared in the base class to ensure that they are available in any derived classes via the