This module focuses on exception handling in C++, teaching how to handle errors and exceptional situations in your code properly.
- Exercise 00: Mommy, when I grow up, I want to be a bureaucrat!
- Exercise 01: Form up, maggots!
- Exercise 02: No, you need form 28B, not 28C...
- Exercise 03: At least this beats coffee-making
- Exception Handling: Using try-catch blocks to handle errors
- Custom Exceptions: Creating and using user-defined exception classes
- Exception Hierarchies: Organizing exceptions in an inheritance structure
- Exception Safety: Ensuring proper resource management during exceptions
- Orthodox Canonical Form: Implementing classes with proper constructors and operators
Exception handling in C++ uses try-catch blocks to manage error conditions:
try {
// Code that might throw an exception
if (something_wrong)
throw std::exception();
}
catch (const std::exception& e) {
// Handle the exception
std::cout << e.what() << std::endl;
}Creating custom exception classes by inheriting from std::exception:
class GradeTooHighException : public std::exception {
public:
virtual const char* what() const throw() {
return "Grade is too high";
}
};
class GradeTooLowException : public std::exception {
public:
virtual const char* what() const throw() {
return "Grade is too low";
}
};Different levels of exception safety:
- Basic Guarantee: No resource leaks or corrupted data
- Strong Guarantee: Operation either succeeds completely or has no effect
- No-throw Guarantee: Operation never throws exceptions
Example:
class Bureaucrat {
private:
const std::string name;
int grade;
public:
// Strong guarantee - either succeeds or throws
Bureaucrat(const std::string& name, int grade) : name(name) {
if (grade < 1)
throw GradeTooHighException();
if (grade > 150)
throw GradeTooLowException();
this->grade = grade;
}
};
class Form {
private:
const std::string name;
bool isSigned;
const int gradeToSign;
public:
// Basic guarantee - no resource leaks
void beSigned(const Bureaucrat& bureaucrat) {
if (bureaucrat.getGrade() > gradeToSign)
throw GradeTooLowException();
isSigned = true;
}
};
class Intern {
public:
// No-throw guarantee - never throws exceptions
Form* makeForm(const std::string& formName, const std::string& target) {
if (formName == "Robotomy Request")
return new RobotomyRequestForm(target);
if (formName == "Presidential Pardon")
return new PresidentialPardonForm(target);
if (formName == "Shrubbery Creation")
return new ShrubberyCreationForm(target);
return NULL;
}
};Using RAII (Resource Acquisition Is Initialization) to manage resources:
class Form {
private:
bool* signed_;
public:
Form() : signed_(new bool(false)) {}
~Form() { delete signed_; }
Form(const Form& other) : signed_(new bool(*other.signed_)) {}
Form& operator=(const Form& other) {
if (this != &other) {
bool* temp = new bool(*other.signed_);
delete signed_;
signed_ = temp;
}
return *this;
}
};Creating a hierarchy of related exceptions:
class FormException : public std::exception {
protected:
std::string message;
public:
FormException(const std::string& msg) : message(msg) {}
virtual const char* what() const throw() {
return message.c_str();
}
};
class GradeTooLowException : public FormException {
public:
GradeTooLowException()
: FormException("Grade is too low for this operation") {}
};
class GradeTooHighException : public FormException {
public:
GradeTooHighException()
: FormException("Grade is too high for this operation") {}
};- Implement a Bureaucrat class with grade limitations
- Create custom exceptions for grade validation
- Practice basic exception handling
Key Implementation:
class Bureaucrat {
private:
const std::string name;
int grade; // 1 to 150
public:
Bureaucrat(const std::string& name, int grade);
void incrementGrade();
void decrementGrade();
// ... other methods
};- Create a Form class with signing requirements
- Implement grade checks for signing and executing
- Practice exception handling with multiple conditions
Key Features:
class Form {
private:
const std::string name;
bool isSigned;
const int gradeToSign;
const int gradeToExecute;
public:
void beSigned(const Bureaucrat& bureaucrat);
// ... other methods
};- Implement different types of forms
- Create concrete form classes with specific actions
- Practice inheritance and polymorphism with exceptions
- Create an Intern class that creates forms
- Implement form creation based on form names
- Practice factory pattern and error handling