Teaching Notes: Module 05
Key Learning Objectives
Section titled “Key Learning Objectives”- Exception handling (try/catch/throw)
- Custom exception classes
- Nested exception classes
- Exception-safe design
Exercise 00: Bureaucrat
Section titled “Exercise 00: Bureaucrat”Key Concepts
Section titled “Key Concepts”- Grade 1 = highest, 150 = lowest
- Increment = grade goes DOWN (more senior)
- Throw exceptions for invalid grades
Common Mistakes
Section titled “Common Mistakes”-
Grade logic backwards
void Bureaucrat::incrementGrade() {_grade++; // WRONG - increment means better = lower number_grade--; // CORRECT} -
Exception class not inheriting std::exception
class GradeTooHighException : public std::exception {const char* what() const throw() {return "Grade is too high";}}; -
Not making name const
const std::string _name;- can’t change after construction
Exercise 01: Form
Section titled “Exercise 01: Form”Key Design
Section titled “Key Design”- Form has grades required to sign AND execute
- Bureaucrat signs Form, Form validates grade
Common Mistakes
Section titled “Common Mistakes”-
Checking wrong direction
// Remember: lower number = betterif (bureaucrat.getGrade() > _gradeToSign)throw GradeTooLowException(); -
signForm() output format
- Success:
<name> signed <form> - Failure:
<name> couldn't sign <form> because <reason>
- Success:
Exercise 02: Abstract Form (AForm)
Section titled “Exercise 02: Abstract Form (AForm)”Key Changes
Section titled “Key Changes”- Form -> AForm (abstract)
- Add
execute(Bureaucrat const&) const - Concrete forms: Shrubbery, Robotomy, Presidential
Execution Requirements
Section titled “Execution Requirements”- Form must be signed
- Executor grade must be high enough
Guiding Questions
Section titled “Guiding Questions”- “Where should execution requirements be checked - base or derived?”
- “Why might it be better to check in the base class?”
Exercise 03: Intern
Section titled “Exercise 03: Intern”The Factory Pattern
Section titled “The Factory Pattern”AForm* Intern::makeForm(const std::string& name, const std::string& target) { // Use function pointers or map, NOT if/else forest}Common Mistakes
Section titled “Common Mistakes”-
Using if/else chain
- Subject explicitly forbids this
- Use array of function pointers
-
Memory management
- Intern creates form, caller must delete
Clean Implementation
Section titled “Clean Implementation”typedef AForm* (*FormCreator)(const std::string&);
AForm* createShrubbery(const std::string& t) { return new ShrubberyCreationForm(t);}// ... other creators ...
AForm* Intern::makeForm(const std::string& name, const std::string& target) { std::string names[] = {"shrubbery creation", "robotomy request", "presidential pardon"}; FormCreator creators[] = {createShrubbery, createRobotomy, createPresidential};
for (int i = 0; i < 3; i++) { if (name == names[i]) { std::cout << "Intern creates " << name << std::endl; return creators[i](target); } } std::cerr << "Form not found: " << name << std::endl; return NULL;}