CSE390C Sample Final, Winter 2024 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.