Comp 272 Study Guide and Sample Exam Dordal Oct 13, 2004 Exam is Monday, Oct 18 Things to study: Chapter 2: you should be familiar with essentially everything here, HOWEVER in general I don't expect perfect syntax on an exam. Chapter 3: ditto for the C++ class syntax. Here are the highlights of C++ that you'll need: input (via cin) and output (via cout) basic types (you know these from Java, though) vector and string classes (basic use, anyway) if, while, etc functions function reference parameters, with & (chapter 3) how to declare classes accessors, mutators, field accessors, field mutators, const constructors member initialization list in ctors importance of default ctors In addition to the above, you should be familiar with the Date class, and variations of Date. Chapter 4: Be familiar with the arguments for keeping data private. The rest of chapter 4 deals with "common sense" for class design. Page 72 introduces the "5 C's (almost)": cohesion, completeness, consistency, convenience, and primitive operations. Chapter 5: Object-oriented *design*. Review both the CRC card method for describing class relationships and the diagram approach. Bear in mind, however, that there won't be enough time on the exam for a significant question on complex class relationships. You should be familiar with the notion that class membership/containment is a HAS-A relationship, while inheritance is an IS-A relationship. Be prepared to produce diagrams such as those on pages 98, 99, 104, and 105. Chapter 6: There will be no *loop* invariants on the exam. Be familiar, though, with what is meant by a *class* invariant. Useful invariants can be hard to come up with on ones own, but you should be able to: (a) given some code, be able to tell whether a statement is an invariant, and (b) given an invariant, be able to write code that adheres to it. Chapter 7: Static inheritance. You should be familiar with the shape classes in general terms. The fundamental examples were: basic classes Point, Rectangle (*uses* Point), Polygon, Text Triangle --> Polygon ScalableText --> Text Given a member function in the base class, the same member function in the derived class can: * be the same as the base class implementation; ie no change * replace the base class implementation * extend the base class implementation One important new technique was calling the base class ctor in the member initialization list. ================================== Here are a few sample questions. Some have been used on past exams; others were rejected as being too hard! Answers will be posted. 1. Consider the following operations in a class Date: class Date { public: Date(int month, int date, int year); String tostring(); void advance(int ndays); // advances the date by a given number of days }; (a). Modify the design of the class so advance() returns a new date, instead of modifying the existing date. Declare the revised version with all applicable uses of "const". (b). Suggest a reasonable collection of accessors that would give you ways to access and use the date. You should be able to convert the entire date to a string, and also extract the year, day, and month fields. (c). Discuss why it would be a bad idea for the Date class to make any of its internal fields public. Try to give at least two fundamental reasons. 2. (a). Consider a banking system, with classes for checking accounts and savings accounts. The Checking_Account class has member functions withdraw(Money amt), deposit(Money amt), and writecheck(Money amt). The Savings_Account class has member functions withdraw and deposit and also AddInterest(double interest_rate). Arrange these classes in a suitable inheritance hierarchy. Introduce a common base class with the appropriate operations. Do not implement any functions; just show what gets declared in what class! 3. Write a C++ function vsearch(v, x, found) to search a vector v of doubles for a given value x. If x is found at position v[i], then i is to be returned and the actual parameter corresponding to found (of type bool) is to be set to "true"; if i is not found then set found=false. Note that found must be a reference parameter (declared with &). 4. (a). Draw class diagrams for the voicemail system, modified so that MailAccount does ALL user interaction and makes appropriate calls to a class member of type MailData to get things done. Specifically, show the relationships between MailData, MailAccount, InputReader, and Message. (b). Our implementation derived AdminMailbox from Mailbox. Yet the MailSystem::process_dialing function still explicitly checked for extension 9999 to determine if a mailbox was an Admin box or not (in other words, no "polymorphism" was used). Given this, what was the advantage (if any) to using inheritance here? 5. Consider the following outline of a list interface. Assume the list are of objects of type X. Note that this interface maintains a "current" element of the list; the internal "cursor" is in effect a pointer to the current element. class listX { public: start() // set an internal "cursor" to start of list next(); // advance cursor to next element set(); // set current element to a new value get(); // return current element add(); // add new element after current cursor position addbefore(); // like add, but inserts new element in front of current delete(); // deletes current element islast(); // true if current element is last element length(); // return length of list ... } (a). Provide parameter lists for all the above, indicating which member functions are const. Also indicate which member function parameters are const (ie where the actual parameter will not be modified). (b). Explain why both add() and addbefore() are necessary; that is, give an example of something that can be done with add() but not addbefore() and something that can be done with addbefore() but not with add(). 6. [This one is a little arcane, but at heart it's just about class interfaces again.] The list class in problem 5 has a disadvantage in that there can be at most one cursor. Implementing a linked-list class with public pointer fields is that one way to support multiple cursors (pointers) into the same list, but the price is that a critical data field is now public, which ties one to a specific implementation, and causes a loss of some type safety. One way to have the best of both worlds is to implement "external iterators"; that is, one has a class List and also a class ListCursor. A ListCursor object represents a pointer into a linked list; alternatively, if the List is implemented as an array, then a ListCursor represents an array index value. All list operations that refer to the "current" element would now be made in terms of a ListCursor object. The class ListCursor would be able to access the private: data of class List, either because ListCursor was declared inside class List, or was declared to be a "friend" class. Specify the interface for List and ListCursor, and indicate with a comment what each operation does. As a hint, a constructor for a ListCursor is specified; it takes a List reference and sets the ListCursor to mark the first element of the list. class List { }; class ListCursor { friend List; public: ListCursor (List & L); // Sets the listcursor to point to head of L }; 7. Define a class Complex (for complex numbers). Do *not* implement any of the operations, though! A complex number should have two data fields, _real and _imag, of type double. You *should* implement the following constructors, though: (a) Complex (double, double); // set _real and _imag (b) Complex (double) // set _real; let _imag = 0; (c) default ctor