Intermediate Project 1 — Virtual Zoo¶
Difficulty: Intermediate · Estimated effort: 10–14 hours · Prerequisites: Module 6 — Inheritance, Module 7 — Polymorphism, Module 8 — Abstract Classes, Module 14 — The STL with OOP · Combines: hierarchy design, virtual dispatch, distinct operations kept in distinct classes, a save/load round trip
This is one of the designated integration projects. It must use, explicitly and in writing: multiple classes · relationships between classes · encapsulation · inheritance or composition · polymorphism · the STL · exception handling.
No complete solution is provided. In particular, the class list is not given: deciding where a behaviour belongs is the project.
1. Scenario¶
A wildlife park keeps a register of its animals, the enclosures they live in, and the keepers who look after them. Feeding differs by species — a carnivore's ration is not a herbivore's — enclosure assignments change, and the park inspector wants a printed schedule plus a written register it can file.
The last attempt put every behaviour in an Animal base class as one giant if on a species
string. It worked until the park added a species.
2. Problem statement¶
Build the park's register as a small system: animals with species-specific behaviour, enclosures that hold them, keepers assigned to enclosures, a daily feeding schedule, and a file format the park can keep.
The design must survive the addition of a new species and a new feeding rule without editing the code that prints the schedule or computes the totals — and you must demonstrate that with a change and a count of the files you touched.
3. User requirements¶
- [ ] Add animals of several species and see them in the register.
- [ ] Assign an animal to an enclosure, and move it.
- [ ] Assign keepers to enclosures and see who is responsible for what.
- [ ] Print a feeding schedule for the day, ordered by time.
- [ ] Save and load the register; a damaged file is refused with a line number.
- [ ] Be refused, with a reason, when an enclosure is over capacity or a move is impossible.
4. Functional requirements¶
- [ ] A species abstraction with per-species feeding behaviour and ration.
- [ ]
Enclosurewith a capacity invariant enforced on every insertion. - [ ]
Keeperwith a name and a set of enclosures. - [ ] A
Parkowning enclosures and animals; animals never owned by two enclosures at once. - [ ] Feeding entries with a time-of-day and an ordering rule, sorted with an STL algorithm.
- [ ] Persistence for animals, enclosures and assignments, with a version marker.
- [ ] A custom exception type for park-rule violations, distinct from file-format errors.
5. Non-functional requirements¶
- [ ] An animal cannot be in two enclosures, and an enclosure cannot exceed capacity — verified from outside by trying.
- [ ] Polymorphic destruction is correct: no leaks, no slicing, virtual destructors.
- [ ] Ownership is explicit; nothing owns an animal twice.
- [ ] A failed load leaves the in-memory park unchanged.
- [ ] Builds warning-free with
g++ -std=c++17 -Wall -Wextra -Werror.
6. Suggested features¶
- A
Visitor-style report object that computes statistics without touching the hierarchy. - Enclosure temperature ranges per species, with a compatibility check on assignment.
- A weekly schedule rather than a daily one, with the ordering rule documented.
- Health records per animal, appended and never edited — and a note on what that forbids.
7. OOP concepts involved¶
| Concept | Required | Where it appears |
|---|---|---|
| Multiple classes | yes | Species abstractions, Animal, Enclosure, Keeper, Park, schedule, error types |
| Relationships | yes | Park ◆ enclosures; enclosure ◆ animals; keeper ◇ enclosures — named in a diagram |
| Encapsulation | yes | Capacity, single-enclosure membership and ration validity live inside their owners |
| Inheritance or composition | yes | Species hierarchy for animals; composition for park and enclosure |
| Polymorphism | yes | Feeding and ration dispatch through the species interface, no if on species |
| The STL | yes | Containers for the register; std::sort for the schedule; std::find_if for lookups |
| Exception handling | yes | Park-rule violations thrown and caught; damaged files distinct from bad requests |
8. Suggested design considerations¶
Decide whether an animal's species is a class or a value. A Species type holding the
species data, with animals composed with it, is often better than a subclass per species — and
it is worth an argument in your design note. Both answers can pass; an unexamined answer cannot.
Separate the schedule from the animals. A schedule is a view produced from the register, not a field on every animal. Keeping it separate is what stops the report code from needing to know the hierarchy.
Watch the two invariants. An animal in one enclosure, and an enclosure within capacity, are the same fact seen from two sides. Enforce them in one place, or they will disagree.
Say what happens on a failed move. Moving an animal between enclosures can fail on capacity. The strong guarantee — either the move happened or nothing changed — is the right default here; say so and test it.
9. Minimum viable version¶
Species abstraction, Animal, Enclosure with capacity, Park owning everything, add/move
operations with refusals, and a printed feeding schedule sorted by time. No persistence yet.
10. Intermediate extension¶
Add persistence with a version marker and a documented field separator, plus three hand-edited
corruptions that must be rejected with line numbers. Then add the Visitor-style statistics
report and confirm that adding a new statistic requires no change in the hierarchy.
11. Advanced extension¶
Add a new species and a new feeding rule, and count the files touched for each. Then convert one part of the register to an interface-plus-strategy design, and report the change cost honestly — including if it got worse. A measured "this was not worth it" is a valid result.
12. Testing checklist¶
- [ ] Adding an animal beyond an enclosure's capacity is refused, and the enclosure is unchanged
- [ ] Moving an animal frees capacity in the old enclosure and consumes it in the new
- [ ] A refused move leaves both enclosures exactly as they were
- [ ] An animal appears in exactly one enclosure's list at all times
- [ ] The schedule is ordered by time; equal times have a documented, deterministic order
- [ ] The ration total for the day equals the sum of the individual rations
- [ ] A new species added later is included in totals and schedule with no edits to those files
- [ ] Save → load → save produces identical files
- [ ] A file with a missing field, a bad number and a duplicated assignment is rejected with a line number each time
- [ ] Every animal and enclosure is destroyed exactly once at program end
13. Documentation checklist¶
- [ ] The ownership diagram with multiplicities, matching the declarations
- [ ] One sentence of responsibility per class
- [ ] The file format's specification and version rule
- [ ] The scheduling and tie-break rules
- [ ] The change-cost table from the advanced extension: feature, files touched, verdict
14. Self-evaluation rubric¶
| Criterion | Excellent looks like | Weight |
|---|---|---|
| Hierarchy design | Behaviour dispatched, not switched; adding a species touches one file | 25% |
| Invariants | Capacity and single-membership hold after every operation, demonstrated | 20% |
| Ownership | Clear, single owners; no leaks; correct polymorphic destruction | 15% |
| Failure handling | Refusals name the reason; failed load and failed move leave state untouched | 15% |
| STL use | Containers and algorithms chosen with stated reasons | 10% |
| Persistence | Documented format, round trip, three corruptions rejected | 10% |
| Documentation | Diagram, responsibilities, format and change costs written down | 5% |
Related: Intermediate projects · Project roadmap · All projects · Module 8 — Abstract Classes