Presentation is loading. Please wait.

Presentation is loading. Please wait.

Ch. 17 Case Study Combining Separate Classes Timothy Budd Oregon State University.

Similar presentations


Presentation on theme: "Ch. 17 Case Study Combining Separate Classes Timothy Budd Oregon State University."— Presentation transcript:

1 Ch. 17 Case Study Combining Separate Classes Timothy Budd Oregon State University

2 2 Introduction How to combine elements from two or more classes when they are not permitted to make changes to the original class. Solving this problem is an excellent illustration of the different uses of inheritance, templates, overloaded functions, and the interactions among these mechanisms.

3 3 Figure 17.1 Class Description for Apple // class Apple // created 1987 by Standard Apple of Ohio class Apple { public: // constructors Apple () : variety("generic") { } Apple (string & v) : variety (v) { } Apple (const Apple & r) : variety (r.variety) { } // apple operations ostream & printOn (ostream & out) { return out << "Apple: " << variety; } private: string variety; };

4 4 Figure 17.2 Class Description for Orange // Orange code // written by Chris (Granny) Smith, 1992 // House of Orange class Orange : public Produce { public: // constructor Orange (); void writeTo (ostream & aStream) { aStream << "Orange"; } };

5 5 Combining Separate Classes Since the class description for apples and oranges are distributed only in binary form, cannot add a new member function to these classes. However, nothing prevents from writing new ordinary functions takes their respective types as arguments.

6 6 Combining Separate Classes Use a single name, print, for the operation of printing to a stream: void print (const Apple & a, ostream & out) { a.printOn(out); } void print (const Orange & a, ostream & out) { a.writeTo(out); }

7 7 Combining Separate Classes Single common function name, print, that can be used for both data types: Apple anApple("Rome"); Orange anOrange; // can print both apples and oranges print (anApple, cout); print (anOrange, cout);

8 8 Unlike Java containers, container in C++ are homogeneous and can hold only one type of value. To combine apples and oranges in the same container, need an adaptor that will convert the type into a more suitable data value. We get one first by defining a common parent class that will describe the behavior that we want all fruit to posses: class Fruit { public: virtual void print (ostream &) = 0; };

9 9 Because the specific implementation of the behavior will be different for each fruit, make the description of this function into a pure virtual method. Using a template method, create a fruit adaptor that will take either an apple or an orange, and satisfy the fruit interface: template class FruitAdaptor : public Fruit { public: FruitAdaptor (T & f) : theFruit(f) { } T & value () { return theFruit; } virtual void print (ostream & out) { print(theFruit, out); } public: T & theFruit; };

10 10 The template argument allows to use the adaptor with both apples and oranges, but always yields a new value that is a subclass of Fruit: Fruit * fruitOne = new FruitAdaptor (anApple); Fruit * fruitTwo = new FruitAdaptor (anOrange); Since we have a common representation for apples and oranges, it is easy to create containers that will hold fruit values: list fruitList; // make a list of fruits fruitList.insert(fruitOne); // add an apple fruitList.insert(fruitTwo); // add an orange

11 11 A template function can simplify the creation of the adaptor, since the template argument types are inferred from the parameter values, and need not be specified when a template function is invoked. template Fruit * newFruit (T & f) { return new FruitAdaptor (f); } Using the newFruit function the fruit types will be inferred from the function arguments, and need not be specified explicitly by the programmer: Fruit * fruitThree = newFruit (anApple); Fruit * fruitFour = newFruit (anOrange)

12 12 We have all the elements necessary to maintain both apples and oranges in the same collection, and to perform polymorphic operations on these values: Apple anApple("Rome"); Orange anOrange; list fruitList; // declare list of pointers to fruits fruitList.insert(newFruit(anApple)); fruitList.insert(newFruit(anOrange)); list ::iterator start = fruitList.begin(); list ::iterator stop = fruitList.end(); // loop over and print out all fruits in container for ( ; start != stop; ++start) { Fruit & aFruit = *start; // get current fruit aFruit.print(cout); }

13 13 Combining Separate Classes Notice how this solution has made use of all the polymorphic mechanisms discussed; –overloaded functions, – template classes –template functions –inheritance –overridding


Download ppt "Ch. 17 Case Study Combining Separate Classes Timothy Budd Oregon State University."

Similar presentations


Ads by Google