CSE390C Sample Final, Winter 2023 handout #7 1. Inheritance Mystery (15 points). Assuming that the following classes have been defined: class foo { public: void f1() { cout << "foo 1" << endl; } virtual void f2() { cout << "foo 2" << endl; } void f3() { cout << "foo 3" << endl; } }; class bar : public foo { public: virtual void f1() { cout << "bar 1" << endl; } void f3() { cout << "bar 3" << endl; } }; class baz : public bar { public: void f1() { cout << "baz 1" << endl; } virtual void f3() { cout << "baz 3" << endl; } }; class mumble : public baz { public: void f1() { cout << "mumble 1" << endl; } void f2() { cout << "mumble 2" << endl; } void f3() { cout << "mumble 3" << endl; } }; And assuming the following variables have been defined: foo * var1 = new mumble(); bar * var2 = new mumble(); baz * var3 = new mumble(); foo * var4 = new bar(); bar * var5 = new baz(); In the table below, indicate in the right-hand column the output produced by the statement in the left-hand column. Statement Output ------------------------------------------------------------ var1->f1(); ____________________________ var2->f1(); ____________________________ var3->f1(); ____________________________ var4->f1(); ____________________________ var5->f1(); ____________________________ var1->f2(); ____________________________ var2->f2(); ____________________________ var3->f2(); ____________________________ var4->f2(); ____________________________ var5->f2(); ____________________________ var1->f3(); ____________________________ var2->f3(); ____________________________ var3->f3(); ____________________________ var4->f3(); ____________________________ var5->f3(); ____________________________ 2. Class definition (25 points). Write a class called string_pair that stores a pair of strings that are heap allocated by calling new. The class should have the following member functions: string_pair(s1, s2) constructs a string_pair from the given string values (each should default to an empty string) string_pair(other_p) constructs a string_pair from another string_pair get_first() returns a const reference to the first string get_second() returns a const reference to the second string to_string() returns a text version of the pair separated by a comma and in parentheses, as in (some, text) Your class should have a destructor and should override the assignment operator. You must write your class in such a way that all memory allocated by your string_pair objects is freed up by calls on delete. You may assume that this class is not part of an inheritance hierarchy. 3. STL Programming (10 points). Write a function called retain_all that takes two sets of integers as parameters and that removes any values in the first set that are not found in the second set. For example, given sets: s1: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] s2: [3, 6, 9, 12, 15, 18, 21, 24] If the following call is made: retain_all(s1, s2); after the call, the sets would store the following values: s1: [6, 12, 18] s2: [3, 6, 9, 12, 15, 18, 21, 24] Notice that s2 is unchanged but s1 now contains only values that are also in s2. 4. STL Programming (15 points). Write a function called convert that takes as a parameter a set of strings representing phone numbers and that returns a map of strings to sets of strings that represent the same phone numbers split into exchange/suffix. In particular, the phone numbers in the set passed to the method will each include a 3-digit exchange followed by a dash followed by a four-digit suffix, as in: (493-3923, 723-9278, 384-1917, 555-1795, 384-4923, 555-4923, 555-1212, 723-9823) The method should split each string into the 3-digit exchanges that come before the dash and the suffixes that come after. The method should construct a map in which the keys are the 3-digit exchanges. Each such exchange will be mapped to a set of 4-digit suffixes. For the set of phone numbers above, the following map would be constructed: ((384, (1917, 4923)), (493, (3923)), (555, (1212, 1795, 4923)), (723, (9278, 9823))) Notice, for example, that three of the phone numbers in the original set began with "555". In the map, the key "555" maps to a set of three elements (the three suffixes that came after "555-"). 5. STL Programming (10 points). Write a function called count_shuffles that takes a vector of int values as a parameter and that randomly shuffles the values until the first half is in sorted order, returning the number of shuffles performed. If the vector has an odd length, then include the middle element in the first half that is to be sorted. For example, if a vector called numbers contains this sequence: [3, 8, 4, 5, 12, 17, 2, 8, 15, 19, 27, 13, 6] then the call count_shuffles(numbers) should randomly shuffle the entire vector of numbers until the first half is sorted. For example, the vector might store these values after the function is called: [3, 6, 8, 8, 12, 13, 15, 19, 2, 27, 17, 5, 4] | | | | +--------------------+ +----------------+ sorted unknown Notice that the function will not always end up with the same values in the first half because the only requirement is that those values appear in sorted order. We won't know anything about the values in the second half. In a sample execution, the count returned was 5251, indicating that it took 5251 random shuffles to end up with the first half being sorted. 6. Inheritance (20 points). Define a base class called printable that will allow us to override the insertion operator ("<<") just once for all of the classes included in this hierarchy. The base class should have a member function called print that takes a reference to an ostream as a parameter. It shouldn't return a value. The base class should be an abstract class and the print member function should be a purely virtual function. Using the virtual print function, you are to override the insertion operator ("<<"). We can create many subclasses that each override print. You will write one such class called quoted_text. It should have a public constructor that takes a string as a parameter. It should print the string surrounded by single quotation marks. For example, this code: printable * p = new quoted_text("hello"); cout << "p = " << *p << endl; delete p; should produce the following output: p = 'hello' You should write your class so that the objects constructed using it do not produce a memory leak. You do not have to worry about a client calling the copy constructor or the assignment operator. Include below your definition for the printable class, the overridden insertion operator, and the quoted_text class. 7. Short answer (5 points). Suppose that you want to loop over a sequence of string values stored in a structure called "data". Often we can use a foreach loop to do so: for (string s : data) { ... } One problem with this approach is that it will make copies of the strings. So it is tempting to want to change this to a loop that uses references to strings: for (string & s : data) { ... } This will be more efficient in that it won't make copies of the strings, but it often doesn't compile even though the other version does. Why not? There are many possible reasons. Describe one.
Stuart Reges
Last modified: Tue Mar 7 14:39:48 PST 2023