42 Seoul

[42Seoul] CPP05 try catch

jaewpark 2022. 7. 23. 14:29

Exercise 00

exception class는 Orthodox Canonical Foam이 지켜지지 않아도 됩니다.

주어진 등급 외의 사용하여 인스턴스화하려는 것에 대해서 예외 처리를 해야 합니다.

  • Bureaucrat::GradeTooHighException
  • Bureaucrat::GradeTooLowException

 

필수적인 요소

  • constant name
  • grade
  • getters
    • getName
    • getGrade
  • member function
    • increment grade 
    • decrement grade
  • overload of the insertion («) operator to print

 


갑작스러운 const에 대한 공부

 

const

constant의 약자로 상수를 의미합니다

 

const 사용

  • const 변수
    : 할당 시 초기화되지 않은 상태로 둘 수 없습니다
const std::string objectName = "chair";
std::string const objectName = "chair";	// 위와 동일한 의미

// const std::string name;	잘못된 접근

// name = "table"		잘못된 접근

 

  • When the pointer variable point to a const value
    : 포인터 변수가 가리키는 값에 대하여 상수화
const data_type* var_name;

/* example */

int x(10);
char y('M');
 
const int* i = &x;
const char* j = &y;

x = 9;
y = 'A';

/*
// Compile Error : read-only variable is not assignable
// *i = 3;
// *j = 'C';
*/

 

  • When the const pointer variable point to the value
    : 포인터 변수 자체를 상수화
data_type* const var_name;

/* example */

int x(7);
int y(42);

int* const i = &x;

// i = &y;	Error

x = 8;

 

  • 위에서 언급된 두 개 모두 const
int num = 1;
const int* const ptr = #

// 참조자는 애초에 참조하는 대상을 변경할 수 없는 특징이 있기 때문에 아래와 같이 사용
const int& ref = num;

 

  • const member function
    : 맴버 함수 내의 모든 맴버 변수를 상수화

 

참고1

참고2

 


Const 멤버 변수를 복사 생성자에?

복상 생성자에서 해당 값을 들고와서 입력을 받기 위해서 Constructor member initializer list(생성자 멤버 초기화 리스트)를 사용하면 입력할 수 있습니다. 코드로 설명을 하자면,

// 불가능
Bureaucrat::Bureaucrat(const Bureaucrat& origin)
{
    this->name = oringin.getName();
    this->grade = origin.getGrade();
}

// 가능
Bureaucrat::Bureaucrat(const Bureaucrat& origin) : name(origin.getName())
{
    this->grade = origin.getGrade();
}

 


try throw catch

명령문을 사용하면 실행 되는 try동안 오류를 테스트할 코드 블록을 정의할 수 있습니다.

문제가 감지되면 키워드에서 throw 예외 (참고) 발생하여 사용자 지정 오류를 생성할 수 있습니다.

 catch명령문을 사용하면 try 블록에서 오류가 발생할 경우 실행할 코드 블록을 정의할 수 있습니다.

try 및 키워드  catch쌍으로 제공

try {
  // Block of code to try
  throw exception; // Throw an exception when a problem arise
}
catch () {
  // Block of code to handle errors
}

std::execption
오동작을 방지하는 프로그램을 설계할 수 있도록 언어 차원에서 자원

std::exception::what (참고)

// C++ 98
virtual const char* what() const throw();

// example
#include <exception>
#include <iostream>

struct ooops : std::exception {
  const char* what() const throw() { return "Ooops!\n"; }
};

int main() {
  try {
    throw ooops();
  } catch (std::exception& ex) {
    std::cout << ex.what();
  }
  return 0;
}
c++ 11 사용되는 specifier
override : In a member function declaration or definition, override specifier ensures that the function is virtual and is overriding a virtual function from a base class
explicit : it cannot be used for implicit conversions and copy-initialization
delete : To disable the usage of a member function. This is done by appending the '=delete;'
default : Explicitly defaulted function declaration is a new form of function declaration that is introduced standard which allows you to append the '=default;'


참고1

참고2

참고3

 


개체 출력자  (참고)

기본 형식의 값을 ostream 형식 개체와 왼쪽 쉬프트(<<) 연산자를 이용하여 스트림에 출력할 때와 같이 사용자가 정의한 형식도 기본 형식처럼 ostream 형식 개체를 이용하여 출력하는 하는 것

// *.hpp
ostream &operator<<(ostream &os,const Bureaucrat &bureaucrat);


// *.cpp
ostream &operator<<(ostream &os,const Bureaucrat &bureaucrat)
{
    // os << 출력하고자 하는 문구
    return os;
}

Exercise 01

Foam 클래스를 만듭니다.

attributes  are private

  • const name
  • bool signed(default false)
  • const grade to sign
  • const grade to execute

등급에 대한 것은 Bureaucrat(ex00 참조)에 따릅니다.

ex00와 동일하게 예외 처리가 필요합니다 (Form::GradeTooHighException, Form::GradeTooLowException)

이전과 마찬가지로 모든 속성에 대해 getter를 작성하고 모든 양식의 정보를 인쇄하는 객체 출력자를 만들면 됩니다.

Bureaucrat을 참조하는 beSigned() member function

Add a signForm() member function to the Bureaucrat. 아래와 같이 출력되어야 합니다.

: <bureaucrat> signed <form> 그렇지 않다면 <bureaucrat> couldn’t sign <form> because <reason>

 


 

Exercise 02

기본 클래스 양식은 추상 클래스여야 합니다

속성은 비공개로 유지되어야 하며 기본 클래스에 있어야 합니다.

concrete classes를 추가 합니다.

  • ShrubberyCreationForm : Required grades: sign 145, exec 137
    작업 디렉터리에 파일 <target>_shrubbery를 만들고 그 안에 ASCII 트리를 작성합니다.
  • RobotomyRequestForm: Required grades: sign 72, exec 45
    구멍 뚫는 소리를 냅니다.
    이후, <target>이 50% 로봇화에 성공했음을 알립니다. 그렇지 않은 경우 로봇 검사가 실패했음을 알립니다.

  • PresidentialPardonForm: Required grades: sign 25, exec 5
    <target>이 사면되었음을 알립니다.

이들 모두 생성자에서 하나의 매개 변수, 즉 양식의 대상만 사용합니다. 예를 들어, 여러분이 집에 관목을 심고 싶다면 "집"이라고 합니다.

이제 기본 폼에 const execute(Bureaucrat const & executor) 멤버 함수를 추가하고 Form의 concrete classes동작을 실행하는 함수를 구현

서명이 되어 있는지, 서식을 실행하려는 관료들의 등급이 충분히 높은지 확인해야 합니다. 그렇지 않으면 적절한 예외를 적용합니다.

concrete class : new 키워드를 사용하여 인스턴스를 만드는 클래스, 구상 클래스

모든 구상 클래스에서 또는 기본 클래스에서 요구 사항을 확인할 것을 권유합니다.

executeForm(Form const & form) 멤버 함수를 the Bureaucrat 에 만듭니다.

성공적인 경우 다음을 인쇄하십시오.

 <bureaucrat> executed <form>

그렇지 않으면 명시적 오류 메시지를 인쇄 해야 합니다.


50% 라는 확률을 사용하기 위해 랜덤함수를 사용

std::rand() (참고)
: Pseudo-random integral value between  0 and RAND_MAX
사용을 위해서 % 연산자를 통해서 값을 제한하고 그 범위 내에서 어떻게 사용할지 정하면 됩니다.

#include <cstdlib>
#include <iostream>

// 0 ~ 99 까지의 숫자가 나옵니다.
int pers = std::rand() % 100;

if (pers < 50)
    std::cout << "under 50" << std::endl;
else
    std::cout << "it's big number. Just joke!!" << std::endl;

 


기본 폼에 const execute(Bureaucrat const & executor) 멤버 함수를 추가하지만 상속받는 자식 클래스에서만 사용이 되기에

순수 가상 함수를 사용해야 합니다. 즉 Form은 abstract class(추상 클래스)가 됩니다.

 


CPP05부터는 통과를 하기 위해서 Exercise03까지 진행을 해야합니다. 어떻게 알았냐구요? ... 알고 싶지 않았습니다

Exercise03

Intern 이라는 클래스를 만들고, 내부 멤버 함수 Form* makeForm(name of form, target of form) 를 만드세요.

if/elseif/else 문을 사용하지 마세요.

예외 처리를 해야 합니다.


if/elseif/else를 사용하지 않고 해당 값을 찾는 방법에는 멤버 함수 포인터(CPP01 ex05 참조)를 사용하면 됩니다.
참고1, 참고2 참고하여서 간략한 예시를 들면,

// 사용된 find는 algorithm.h에 속해있습니다.

Animal *ret = NULL;
Animal *(*func[5])(std::string name) = {makeCat, makeDog, ...}
std::string types[] = {"cat", "dog", ...}
std::string *pick = std::find(types, types + types.size(), type);
if (pick == types + types.size()) {
  std::cerr << "Wrong complain! Try again!" << std::endl;
} else {
  ret = (func[pick - tpyes])(std::string name);
}
return ret;