Multiple Inheritance (MI) Describes a class that has multiple direct base classes. As with single inheritance, the total MI representation is also a is-a relationship. For example, you can derive the Singingwaiter class from the Awiter class and the singer class:
Class Singingwaiter:public Waiter, public Singer {...};
MI may bring many new problems to the programmer. The two main problems are: Inherit the same name method from two different base classes, and inherit multiple instances of the same class from two or more related base classes.
In the following example, we will define an abstract base class worker and use it to derive the waiter class and the singer class. Then, use Mi to derive the Singingwaiter class from the waiter class and the singer class.
Program Listing 14.7 Worker0.h
//Worker0.h--Working classes#ifndef Worker0_h_#defineWorker0_h_#include<string>classWorker//An abstract base class{Private: std::stringfullname; LongID; Public: Worker (): FullName ("no One"), ID (0L) {} Worker (ConstSTD::string& S,LongN): FullName (s), ID (n) {}Virtual~worker () =0;//Pure virtual destructor Virtual voidSet (); Virtual voidShow ()Const;};classWaiter: Publicworker{Private: intPanache; Public: Waiter (): Worker (), Panache (0) {} waiter (ConstSTD::string& S,LongNintp =0): Worker (S, N), panache (p) {} waiter (ConstWorker & wk,intp =0): Worker (wk), panache (p) {}voidSet (); voidShow ()Const;};classSinger: Publicworker{protected: enum{Other, alto, contralto, soprano, bass, baritone, tenor}; enum{vtypes =7};Private: Static Char*pv[vtypes];//string Equivs of voice types intVoice; Public: Singer (): Worker (), voice (other) {} Singer (ConstSTD::string& S,LongNintv =Other ): Worker (S, N), voice (v) {} Singer (ConstWorker & wk,intv =Other ): Worker (wk), voice (v) {}voidSet (); voidShow ()Const;};#endif //Worker0_h_
The class declaration in listing 14.7 contains some internal variables that represent the type of sound. An enumeration type symbol constant alto, contralto, etc. represents a sound type, static array PV stores a pointer to the corresponding C-style string, listing 14.8 initializes the array, and provides a definition of the method.
Program Listing 14.8 Worker0.cpp
//Worker0.cpp--working class methods#include"worker0.h"#include<iostream>usingstd::cout;usingstd::cin;usingStd::endl;//Worker Methods//must implement virtual destructor, even if pureworker::~Worker () {}voidWorker::set () {cout<<"Enter worker ' s name:"; Getline (CIN, FullName); cout<<"Enter worker ' s ID:"; CIN>>ID; while(CIN.)Get() !='\ n') Continue;}voidWorker::show ()Const{cout<<"Name:"<< FullName <<"\ n"; cout<<"Employee ID:"<< ID <<"\ n";}//Waiter MethodsvoidWaiter::set () {worker::set (); cout<<"Enter Waiter ' s panache Rating:"; CIN>>Panache; while(CIN.)Get() !='\ n') Continue;}voidWaiter::show ()Const{cout<<"category:waiter\n"; Worker::show (); cout<<"Panache Rating:"<< Panache <<"\ n";}//Singer MethodsChar* Singer::p v[] = {" Other","Alto","Contralto", "soprano","Bass","baritone","Tenor"};voidSinger::set () {worker::set (); cout<<"Enter number for singer ' s vocal range:\n"; inti; for(i =0; i < vtypes; i + +) {cout<< I <<": "<< Pv[i] <<" "; ifI4==3) cout<<Endl; } ifI4!=0) cout<<Endl; while(Cin >> Voice && (voice <0|| Voice >=vtypes)) cout<<"Please enter a value >= 0 and <"<< Vtypes <<Endl; while(CIN.)Get() !='\ n') Continue;}voidSinger::show ()Const{cout<<"category:singer\n"; Worker::show (); cout<<"Vocal Range:"<< Pv[voice] <<Endl;}
Listing 14.9 is a short program that tests these classes using a multiple array of pointers.
Program Listing 14.9 Worktest.cpp
//worktest.cpp--Test worker class hierarchy#include <iostream>#include"worker0.h"Const intLIM =4;intMain () {Waiter Bob ("Bob Apple",314L,5); Singer Bev ("Beverly Hills",522L,3); Waiter W_temp; Singer s_temp; Worker* Pw[lim] = {&bob, &bev, &w_temp, &s_temp}; inti; for(i =2; i < LIM; i + +) Pw[i]-Set (); for(i =0; i < LIM; i + +) {Pw[i]-Show (); Std::cout<<Std::endl; } return 0;}
Effect:
Enter worker ' s Name:waldo dropmasterenter Worker's Id:442enter waiter ' s panache rating:3enter worker ' s Name:sylvis Sir Enneenter worker ' s id:555enter number for singer ' s vocal range:0: Other 1:alto 2:contralto 3:soprano 4 : Bass 5:baritone 6:tenor 3category:waitername:bob appleemployee id:314panache Rating:5category:singer Name:beverly hillsemployee id:522vocal Range:sopranoCategory:waiterName:Waldo dropmasteremployee id:442panache ratin G:3category:singername:sylvis Sirenneemployee id:555vocal Range:soprano
This design looks plausible: Use the waiter pointer to invoke Waiter::show () and Waiter::set (), and use the singer pointer to invoke Singer::show () and Singer::set (). Then, if you add a Singingwaiter class that derives from the singer and waiter classes, there are some problems. Specifically, the following issues occur.
* How many workers are there?
* which method?
C + + Primer Plus 14.3 Multiple inheritance learning notes