Skip to content

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.
  • [ ] Enclosure with a capacity invariant enforced on every insertion.
  • [ ] Keeper with a name and a set of enclosures.
  • [ ] A Park owning 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