CSE2050 Exam #3. Open book, open notes. Name __________________________ 1. (30 pts). Add the two methods below that are required because of the destructor. class Box { protected: Contents *p; public: Box(const Contents& c): p(new Contents(c)) {} virtual ~Box() {delete p;} virtual double price() const {return p->price();} // The destructor is not empty, so we need copy and =. // The copy constructor must create a new Contents by copying // the Contents of the other Box (not copying p). // We know from the above example that Contents must have a // public copy constructor. Box(const Box& b): p(new Contents(*b.p)) {} // The assignment operator must assign the Contents (not p). // We don't need to check for assignment for self, because the // Contents assignment operator should be responsible for this. Box& operator=(const Box& b) { *p = *b.p; return *this; } // An alternative assignment is to delete the old Contents // and copy a new one. This requires no assumptions about // the Contents assignment operator. In this case, we must // not delete ourself. // // Box& operator=(const Box& b) { // if (&b != this) { // delete p; // p = new Contents(*b.p); // } // return *this; // } }; 2. (30 pts). A Gift is Box except that the price is increased by 1.50 to cover the cost of gift wrap. Derive Gift from Box, write a constructor taking a Contents, and override the price() method. Add other members if and only if they are needed. For instance, if c is a Contents with c.price() returning 3.99, then: Box b(c); cout << b.price() << endl; // 3.99 Gift g(c); cout << g.price() << endl; // 5.49 class Gift: public Box { public: Gift(const Contents& c): Box(c) {} // Do not initialize p double price() const {return p->price() + 1.50;} }; // We do not need a destructor because ~Box() handles deleting p. // Therefore we do not need a copy constructor or assignment // operator either. We do not need any new data members. 3. For b and g above, which of the following statements are errors? For those that are not, what do they print? (4 pts each) Gift *gp = &b; cout << gp->price() << endl; // Error (no base to derived) Box *bp = &g; cout << bp->price() << endl; // 5.49 (points to g) Box &br = g; cout << br.price() << endl; // 5.49 (refers to g) const Box &cbr = br; cout << cbr.price() << endl; // 5.49 (OK, price() is const) cout << Box(g).price() << endl; // 3.99 (a temporary Box) b = g; cout << b.price() << endl; // 3.99 (b is still a Box) 4. Is Box abstract? (4 pts) No. It is possible to create Box objects (because it has a public constructor and no PURE virtual methods). 5. Would your code in part 2 work if Box::p were private? (4 pts) No, in the example above. However, if you don't use p in question 2, then the answer is Yes. For instance, if you wrote: double price() const {return Box::price() + 1.50;} // p could be private 6. Suppose that Gift had a destructor. Give an example where it should be called but would not be if ~Box() were not virtual (8 pts). // Deleting a base pointer to a derived object, for instance: Box *bp = new Gift(c); delete bp; // Which destructor?