第2章:課題の実装
はじめに
本章では、CPP Module 05の各演習を実装します。
---
1. ex00: Mommy, when I grow up, I want to be a bureaucrat!
1.1 課題の要件
- Bureaucratクラス(name, grade)
- gradeは1(最高)から150(最低)
- 範囲外でGradeTooHighException/GradeTooLowException
- incrementGrade/decrementGradeメソッド
<<演算子オーバーロード
1.2 Bureaucratクラス
// Bureaucrat.hpp
#ifndef BUREAUCRAT_HPP
#define BUREAUCRAT_HPP
#include <string>
#include <iostream>
#include <exception>
class Bureaucrat {
public:
class GradeTooHighException : public std::exception {
public:
const char* what() const throw();
};
class GradeTooLowException : public std::exception {
public:
const char* what() const throw();
};
private:
const std::string _name;
int _grade;
static const int HIGHEST_GRADE = 1;
static const int LOWEST_GRADE = 150;
public:
Bureaucrat();
Bureaucrat(const std::string& name, int grade);
Bureaucrat(const Bureaucrat& other);
Bureaucrat& operator=(const Bureaucrat& other);
~Bureaucrat();
const std::string& getName() const;
int getGrade() const;
void incrementGrade();
void decrementGrade();
};
std::ostream& operator<<(std::ostream& os, const Bureaucrat& bureaucrat);
#endif
// Bureaucrat.cpp
#include "Bureaucrat.hpp"
// 例外クラスの実装
const char* Bureaucrat::GradeTooHighException::what() const throw() {
return "Grade is too high";
}
const char* Bureaucrat::GradeTooLowException::what() const throw() {
return "Grade is too low";
}
// コンストラクタ
Bureaucrat::Bureaucrat() : _name("Unknown"), _grade(LOWEST_GRADE) {}
Bureaucrat::Bureaucrat(const std::string& name, int grade) : _name(name) {
if (grade < HIGHEST_GRADE) {
throw GradeTooHighException();
}
if (grade > LOWEST_GRADE) {
throw GradeTooLowException();
}
_grade = grade;
}
Bureaucrat::Bureaucrat(const Bureaucrat& other)
: _name(other._name), _grade(other._grade) {}
Bureaucrat& Bureaucrat::operator=(const Bureaucrat& other) {
if (this != &other) {
// _name is const, cannot be assigned
_grade = other._grade;
}
return *this;
}
Bureaucrat::~Bureaucrat() {}
// ゲッター
const std::string& Bureaucrat::getName() const {
return _name;
}
int Bureaucrat::getGrade() const {
return _grade;
}
// グレード操作
void Bureaucrat::incrementGrade() {
if (_grade <= HIGHEST_GRADE) {
throw GradeTooHighException();
}
_grade--;
}
void Bureaucrat::decrementGrade() {
if (_grade >= LOWEST_GRADE) {
throw GradeTooLowException();
}
_grade++;
}
// ストリーム演算子
std::ostream& operator<<(std::ostream& os, const Bureaucrat& bureaucrat) {
os << bureaucrat.getName() << ", bureaucrat grade " << bureaucrat.getGrade();
return os;
}
// main.cpp
#include "Bureaucrat.hpp"
int main() {
std::cout << "=== Valid Bureaucrat ===" << std::endl;
try {
Bureaucrat bob("Bob", 50);
std::cout << bob << std::endl;
bob.incrementGrade();
std::cout << "After increment: " << bob << std::endl;
bob.decrementGrade();
std::cout << "After decrement: " << bob << std::endl;
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
std::cout << "\n=== Grade Too High ===" << std::endl;
try {
Bureaucrat highBob("HighBob", 0);
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
std::cout << "\n=== Grade Too Low ===" << std::endl;
try {
Bureaucrat lowBob("LowBob", 151);
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
std::cout << "\n=== Increment at Grade 1 ===" << std::endl;
try {
Bureaucrat topBob("TopBob", 1);
std::cout << topBob << std::endl;
topBob.incrementGrade(); // throws
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
return 0;
}
---
2. ex01: Form up, maggots!
2.1 課題の要件
2.2 Formクラス
// Form.hpp
#ifndef FORM_HPP
#define FORM_HPP
#include <string>
#include <iostream>
#include <exception>
class Bureaucrat;
class Form {
public:
class GradeTooHighException : public std::exception {
public:
const char* what() const throw();
};
class GradeTooLowException : public std::exception {
public:
const char* what() const throw();
};
private:
const std::string _name;
bool _signed;
const int _gradeToSign;
const int _gradeToExecute;
public:
Form();
Form(const std::string& name, int gradeToSign, int gradeToExecute);
Form(const Form& other);
Form& operator=(const Form& other);
~Form();
const std::string& getName() const;
bool isSigned() const;
int getGradeToSign() const;
int getGradeToExecute() const;
void beSigned(const Bureaucrat& bureaucrat);
};
std::ostream& operator<<(std::ostream& os, const Form& form);
#endif
// Form.cpp
#include "Form.hpp"
#include "Bureaucrat.hpp"
const char* Form::GradeTooHighException::what() const throw() {
return "Form grade is too high";
}
const char* Form::GradeTooLowException::what() const throw() {
return "Form grade is too low";
}
Form::Form()
: _name("Default"), _signed(false), _gradeToSign(150), _gradeToExecute(150) {}
Form::Form(const std::string& name, int gradeToSign, int gradeToExecute)
: _name(name), _signed(false), _gradeToSign(gradeToSign), _gradeToExecute(gradeToExecute) {
if (gradeToSign < 1 || gradeToExecute < 1) {
throw GradeTooHighException();
}
if (gradeToSign > 150 || gradeToExecute > 150) {
throw GradeTooLowException();
}
}
Form::Form(const Form& other)
: _name(other._name),
_signed(other._signed),
_gradeToSign(other._gradeToSign),
_gradeToExecute(other._gradeToExecute) {}
Form& Form::operator=(const Form& other) {
if (this != &other) {
_signed = other._signed;
}
return *this;
}
Form::~Form() {}
const std::string& Form::getName() const { return _name; }
bool Form::isSigned() const { return _signed; }
int Form::getGradeToSign() const { return _gradeToSign; }
int Form::getGradeToExecute() const { return _gradeToExecute; }
void Form::beSigned(const Bureaucrat& bureaucrat) {
if (bureaucrat.getGrade() > _gradeToSign) {
throw GradeTooLowException();
}
_signed = true;
}
std::ostream& operator<<(std::ostream& os, const Form& form) {
os << "Form " << form.getName()
<< " [signed: " << (form.isSigned() ? "yes" : "no")
<< ", grade to sign: " << form.getGradeToSign()
<< ", grade to execute: " << form.getGradeToExecute() << "]";
return os;
}
2.3 Bureaucrat::signForm()
// Bureaucrat.hppに追加
void signForm(Form& form);
// Bureaucrat.cppに追加
#include "Form.hpp"
void Bureaucrat::signForm(Form& form) {
try {
form.beSigned(*this);
std::cout << _name << " signed " << form.getName() << std::endl;
} catch (const std::exception& e) {
std::cout << _name << " couldn't sign " << form.getName()
<< " because " << e.what() << std::endl;
}
}
---
3. ex02: No, you need form 28B, not 28C...
3.1 課題の要件
- execute()メソッド
3.2 AFormクラス
// AForm.hpp
#ifndef AFORM_HPP
#define AFORM_HPP
#include <string>
#include <iostream>
#include <exception>
class Bureaucrat;
class AForm {
public:
class GradeTooHighException : public std::exception {
const char* what() const throw();
};
class GradeTooLowException : public std::exception {
const char* what() const throw();
};
class FormNotSignedException : public std::exception {
const char* what() const throw();
};
protected:
virtual void executeAction() const = 0;
private:
const std::string _name;
bool _signed;
const int _gradeToSign;
const int _gradeToExecute;
public:
AForm();
AForm(const std::string& name, int gradeToSign, int gradeToExecute);
AForm(const AForm& other);
AForm& operator=(const AForm& other);
virtual ~AForm();
const std::string& getName() const;
bool isSigned() const;
int getGradeToSign() const;
int getGradeToExecute() const;
void beSigned(const Bureaucrat& bureaucrat);
void execute(const Bureaucrat& executor) const;
};
std::ostream& operator<<(std::ostream& os, const AForm& form);
#endif
// AForm.cpp
#include "AForm.hpp"
#include "Bureaucrat.hpp"
const char* AForm::FormNotSignedException::what() const throw() {
return "Form is not signed";
}
void AForm::execute(const Bureaucrat& executor) const {
if (!_signed) {
throw FormNotSignedException();
}
if (executor.getGrade() > _gradeToExecute) {
throw GradeTooLowException();
}
executeAction();
}
3.3 ShrubberyCreationForm
// ShrubberyCreationForm.hpp
#ifndef SHRUBBERYCREATIONFORM_HPP
#define SHRUBBERYCREATIONFORM_HPP
#include "AForm.hpp"
#include <fstream>
class ShrubberyCreationForm : public AForm {
private:
std::string _target;
protected:
void executeAction() const;
public:
ShrubberyCreationForm();
ShrubberyCreationForm(const std::string& target);
ShrubberyCreationForm(const ShrubberyCreationForm& other);
ShrubberyCreationForm& operator=(const ShrubberyCreationForm& other);
~ShrubberyCreationForm();
};
#endif
// ShrubberyCreationForm.cpp
#include "ShrubberyCreationForm.hpp"
ShrubberyCreationForm::ShrubberyCreationForm()
: AForm("ShrubberyCreationForm", 145, 137), _target("default") {}
ShrubberyCreationForm::ShrubberyCreationForm(const std::string& target)
: AForm("ShrubberyCreationForm", 145, 137), _target(target) {}
ShrubberyCreationForm::ShrubberyCreationForm(const ShrubberyCreationForm& other)
: AForm(other), _target(other._target) {}
ShrubberyCreationForm& ShrubberyCreationForm::operator=(const ShrubberyCreationForm& other) {
if (this != &other) {
AForm::operator=(other);
_target = other._target;
}
return *this;
}
ShrubberyCreationForm::~ShrubberyCreationForm() {}
void ShrubberyCreationForm::executeAction() const {
std::ofstream file((_target + "_shrubbery").c_str());
if (!file) {
throw std::runtime_error("Failed to create file");
}
file << " _-_" << std::endl;
file << " /~~ ~~\\" << std::endl;
file << " /~~ ~~\\" << std::endl;
file << "{ }" << std::endl;
file << " \\ _- -_ /" << std::endl;
file << " ~ \\\\ // ~" << std::endl;
file << "_- - | | _- _" << std::endl;
file << " _ - | | -_" << std::endl;
file << " // \\\\" << std::endl;
file.close();
}
3.4 RobotomyRequestForm
// RobotomyRequestForm.hpp
#ifndef ROBOTOMYREQUESTFORM_HPP
#define ROBOTOMYREQUESTFORM_HPP
#include "AForm.hpp"
#include <cstdlib>
#include <ctime>
class RobotomyRequestForm : public AForm {
private:
std::string _target;
protected:
void executeAction() const;
public:
RobotomyRequestForm();
RobotomyRequestForm(const std::string& target);
RobotomyRequestForm(const RobotomyRequestForm& other);
RobotomyRequestForm& operator=(const RobotomyRequestForm& other);
~RobotomyRequestForm();
};
#endif
// RobotomyRequestForm.cpp
#include "RobotomyRequestForm.hpp"
RobotomyRequestForm::RobotomyRequestForm()
: AForm("RobotomyRequestForm", 72, 45), _target("default") {}
RobotomyRequestForm::RobotomyRequestForm(const std::string& target)
: AForm("RobotomyRequestForm", 72, 45), _target(target) {}
RobotomyRequestForm::RobotomyRequestForm(const RobotomyRequestForm& other)
: AForm(other), _target(other._target) {}
RobotomyRequestForm& RobotomyRequestForm::operator=(const RobotomyRequestForm& other) {
if (this != &other) {
AForm::operator=(other);
_target = other._target;
}
return *this;
}
RobotomyRequestForm::~RobotomyRequestForm() {}
void RobotomyRequestForm::executeAction() const {
std::cout << "* DRILLING NOISES *" << std::endl;
srand(time(NULL));
if (rand() % 2) {
std::cout << _target << " has been robotomized successfully!" << std::endl;
} else {
std::cout << "Robotomy on " << _target << " failed." << std::endl;
}
}
3.5 PresidentialPardonForm
// PresidentialPardonForm.hpp
#ifndef PRESIDENTIALPARDONFORM_HPP
#define PRESIDENTIALPARDONFORM_HPP
#include "AForm.hpp"
class PresidentialPardonForm : public AForm {
private:
std::string _target;
protected:
void executeAction() const;
public:
PresidentialPardonForm();
PresidentialPardonForm(const std::string& target);
PresidentialPardonForm(const PresidentialPardonForm& other);
PresidentialPardonForm& operator=(const PresidentialPardonForm& other);
~PresidentialPardonForm();
};
#endif
// PresidentialPardonForm.cpp
#include "PresidentialPardonForm.hpp"
PresidentialPardonForm::PresidentialPardonForm()
: AForm("PresidentialPardonForm", 25, 5), _target("default") {}
PresidentialPardonForm::PresidentialPardonForm(const std::string& target)
: AForm("PresidentialPardonForm", 25, 5), _target(target) {}
PresidentialPardonForm::PresidentialPardonForm(const PresidentialPardonForm& other)
: AForm(other), _target(other._target) {}
PresidentialPardonForm& PresidentialPardonForm::operator=(const PresidentialPardonForm& other) {
if (this != &other) {
AForm::operator=(other);
_target = other._target;
}
return *this;
}
PresidentialPardonForm::~PresidentialPardonForm() {}
void PresidentialPardonForm::executeAction() const {
std::cout << _target << " has been pardoned by Zaphod Beeblebrox." << std::endl;
}
3.6 Bureaucrat::executeForm()
// Bureaucrat.hppに追加
void executeForm(const AForm& form);
// Bureaucrat.cppに追加
void Bureaucrat::executeForm(const AForm& form) {
try {
form.execute(*this);
std::cout << _name << " executed " << form.getName() << std::endl;
} catch (const std::exception& e) {
std::cout << _name << " couldn't execute " << form.getName()
<< " because " << e.what() << std::endl;
}
}
---
4. ex03: At least this beats coffee-making(Bonus)
4.1 課題の要件
4.2 Internクラス
// Intern.hpp
#ifndef INTERN_HPP
#define INTERN_HPP
#include <string>
#include "AForm.hpp"
class Intern {
public:
Intern();
Intern(const Intern& other);
Intern& operator=(const Intern& other);
~Intern();
AForm* makeForm(const std::string& formName, const std::string& target);
private:
AForm* makeShrubbery(const std::string& target);
AForm* makeRobotomy(const std::string& target);
AForm* makePardon(const std::string& target);
};
#endif
// Intern.cpp
#include "Intern.hpp"
#include "ShrubberyCreationForm.hpp"
#include "RobotomyRequestForm.hpp"
#include "PresidentialPardonForm.hpp"
Intern::Intern() {}
Intern::Intern(const Intern& other) { (void)other; }
Intern& Intern::operator=(const Intern& other) { (void)other; return *this; }
Intern::~Intern() {}
AForm* Intern::makeShrubbery(const std::string& target) {
return new ShrubberyCreationForm(target);
}
AForm* Intern::makeRobotomy(const std::string& target) {
return new RobotomyRequestForm(target);
}
AForm* Intern::makePardon(const std::string& target) {
return new PresidentialPardonForm(target);
}
AForm* Intern::makeForm(const std::string& formName, const std::string& target) {
std::string formNames[] = {
"shrubbery creation",
"robotomy request",
"presidential pardon"
};
AForm* (Intern::*formCreators[])(const std::string&) = {
&Intern::makeShrubbery,
&Intern::makeRobotomy,
&Intern::makePardon
};
for (int i = 0; i < 3; i++) {
if (formNames[i] == formName) {
std::cout << "Intern creates " << formName << std::endl;
return (this->*formCreators[i])(target);
}
}
std::cerr << "Intern cannot create form: " << formName << std::endl;
return NULL;
}
// main.cpp
#include "Intern.hpp"
#include "Bureaucrat.hpp"
int main() {
Intern someRandomIntern;
AForm* form1 = someRandomIntern.makeForm("shrubbery creation", "home");
AForm* form2 = someRandomIntern.makeForm("robotomy request", "Bender");
AForm* form3 = someRandomIntern.makeForm("presidential pardon", "Bob");
AForm* form4 = someRandomIntern.makeForm("unknown form", "target");
Bureaucrat boss("Boss", 1);
if (form1) {
boss.signForm(*form1);
boss.executeForm(*form1);
delete form1;
}
if (form2) {
boss.signForm(*form2);
boss.executeForm(*form2);
delete form2;
}
if (form3) {
boss.signForm(*form3);
boss.executeForm(*form3);
delete form3;
}
return 0;
}
---
まとめ
本章で実装した内容: