Section 4 - Multiple Inheritance in Practice
10A.4.1 Cell Phones for Sale
We want to make some money off these phones. So, we'll combine the CellPhone data with the InventoryItem data and produce a new data type: CellPhoneForSale. It will be multiply inherited from the two earlier classes and add a price member. It will therefore have:
- All the CellPhone data (inherited)
- All the InventoryItem data (inherited)
- price (an int)
There are two overloaded constructors and a show() method.
Prototype for CellPhoneForSale
// ----------- class CellPhoneForSale ----------- class CellPhoneForSale : public CellPhone, public InventoryItem { private: int price; public: CellPhoneForSale( string dscr, int mem = 100, feature f1 = no, feature f2 = no, int numstck = 1, int itmno = 0, int price = 0.0); CellPhoneForSale( CellPhone &phone, InventoryItem &invitm, int price); void show(); };
Because we have so many members inherited from the two base classes, one of the constructors has a long list of members. I divided the prototype for that long constructor into three lines: the first contains parameters for the CellPhone, the second for the InventoryItem, and the third the new price member data.
Also, to keep the illustration simple and to-the-point, I'm not supplying a mutator or doing filtering for price. In a real project, we'd have to add all that.
We see that it may be easier for a client, to first create the CellPhone and Inventory item before creating this object, and then pass those two pre-built objects into the second overloaded variant of the constructor. Don't be confused by this. If the client does create those objects first, they are not part of the CellPhoneForSale, but merely convenient boxes from which we can copy the data into the CellPhoneForSale that we are constructing.
CellPhoneForSaleImplementation
// CellPhoneForSale method definitions ----------------- CellPhoneForSale::CellPhoneForSale( string dscr, int mem, feature f1, feature f2, int numstck, int itmno, int price) : CellPhone(dscr, mem, f1, f2), InventoryItem(dscr, numstck, itmno) { this->price = price; } CellPhoneForSale::CellPhoneForSale( CellPhone &phone, InventoryItem &invitm, int price) : CellPhone(phone), InventoryItem(invitm), price(price) { } void CellPhoneForSale::show() { cout <<"\n-------- Phone for sale: ------\n"; CellPhone::show(); InventoryItem::show(); cout << "Retail price: " << price << endl; cout << "-------------------------------\n"; }
Now you can see the concepts of the first part of this lesson more clearly. In the show() method we are disambiguating the show() methods of the two base classes clearly. This is a beautiful example of a derived class using what it has available to it. Call the methods you can (the two show() methods) and deal manually with what is your responsibility (the price field). Although I used two different techniques for initializing price in the two overloaded constructors, remember that in practice we would not take any short cuts, and we would certainly check the value of price for validity before assigning it. This is just good form.
10A.4.2 The Client
Here is the main() that drives it all:
int main() { CellPhone cp1("Erricson Slim", 200, CellPhone::yes, CellPhone::no); CellPhone cp2 ("Motorola Lite", 110, CellPhone::yes, CellPhone::yes); InventoryItem ii1("The Erricson Phone", 5, 11111); CellPhoneForSale cpfs1(cp1, ii1, 405); CellPhoneForSale cpfs2("AT&T Super", 150, CellPhone::no, CellPhone::yes, 3, 22222, 150); cp1.show(); cp2.show(); cout << endl; ii1.show(); cout << endl; cpfs1.show(); cpfs2.show(); }
And a screen shot of the output:

For your convenience, I've placed everything into one listing on the following page. You can copy and paste it to make sure it runs on your platform, and experiment with it if you wish.