왜 예외처리가 필요한가?

대표적인 예외처리는 아래와 같다.
  • 컴퓨터에 사용 가능한 메모리가 부족한 경우
  • 하드디스크에 파일을 쓰는데 하드디스크의 남을 용량이 부족한 경우
  • 사용자가 범위 밖의 값을 입력하거나 존재하지 않는 파일의 이름을 입력한 경우

여기서 중요한것은 버가느 오류같이 개발자의 실수로 일어나는 문제점들과 예외를 구별할 줄 알아야 한다.

DynamicArray.h 보기

DynamicArray.cpp 보기

main.c

반환 값을 사용한 예외처리

DynamicArray 클래스의 SetAt(), GetAt() 함수에는 문제점이 있다. SetAt()함수에는 원소의 인덱스를 넘겨주게 되어 있는데 배열의 크기를 넘겨서 인덱스를 넘겨주는 경우에는 할당 되지 않는 메모리를 건드려서 프로그램이 비정상 종료할 수 있다.
DynamicArray.cpp
bool void DynamicArray::SetAt(int index, int value)
{
    if(index < 0 || index >= GetSize())
    {
        return false;
    }

    arr[index] = value;

    return true;
}
example.cpp
#include "DynamicArray.h"
#include <iostream>
using namespace std;

int main()
{
    // 크기가 10인 배열 객체를 만든다.
    DynamicArray arr(10);

    // 올바른 인덱스를 참조한다
    bool b;
    b = arr.SetAt(5, 0);
    if(false == b)
    {
        cout << "arr[5]  사용실패!!" << endl;
    }

    // 각 원소에 10, 20, 30.. 순으로
    for(int i = 0; i < 10; ++i)
    {
        arr.SetAt(i, (i + 1) * 10);
    }

    // 배열의 크기를 출력하고, 각 원소의 값을 역순으로 출력
    cout << "Size of arr = " << arr.GetSize() << endl;

    for(i = 9; i >= 0; --i)
    {
        cout << "arr[" << i << "] = " << arr.GetAt(i) << endl;
    }

    return 0;
}
여기서 SetAt() 함수에 잘못된 인덱스를 넘긴 사실은 '예외 상황'이 되고, SetAt() 함수에서 이를 감지한 후에 예외 상황을 외부에 알리는 과정이 '예외 처리'라고 볼 수 있다.

반환 값을 사용한 예외처리의 문제점
  • 함수를 호출할 때마다 매번 반환 값을 비교하는 번거러움
  • 이미 함수가 다른 용도의 반환 값을 사용하는 경우
  • 본연의 소스 코드와 예외 처리 코드가 섞여 지저분 해지고 가독성이 떨어진다.

구조적 예외 처리

구조적 예외 처리를 위한 세가지 키워드
  • try
    • 예외가 발생하는지 지켜보는 키워드
    • 일종의 if문과 비슷하다.
  • catch
    • 예외를 잡아서 처리하는 키워드
  • throw
    • 예외 발생시, 예외를 지켜라고 지시하는 키워드
#include <iostream>

using namespace std;

int main()
{
    try
    {
        cout << "Try 1" << endl;
        
        // throw 99;               // 이곳에서 점프하게 된다.
        throw 99.1f;               // 이곳에서 점프하게 된다.
        
        cout << "Try 2" << endl;
    }

    catch(int n)    // throw가 int 형을 던졌을 경우
    {
        cout << "Catch 1 :: " << n << endl;
    }

    catch(float n)    // throw가 float형을 던졌을 경우
    {
        cout << "Catch 2 :: " << n << endl;
    }

    cout << "End Program" << endl;
    
    return 0;
}

throw가 int 값을 던질 경우


throw가 float 값을 던질 경우


try와 catch는 항상 짝을 이뤄서 사용하게 된다.
  • catch 블럭은 오직 한 가지 타입의 값만 받는다
  • try 블럭 안에서 발생하는 예외만 이어지는 catch 블럭에 잡힌다.
  • throw에 의해서 던져지면 그 함수는 즉시 종료 된다.
  • throw에 의해서 던져진 예외는 함수를 뛰어 넘어서까지 전달된다.

예외 객체의 사용

기본 값 대신에 객체를 던지는 것도 가능. 어떤 장점이 있는가?
  • 다양한 정보 전달 가능
  • 다향성을 이용한 일관된 관리가 가능

더보기

  • 예외로 던질 객체에 대한 클래스를 정의한다.
  • 예외에 관한 정보를 담을 멤버 변수들을 정의 한다.
  • 예외 객체의 생성을 편리하게 하기 위한 생성자를 만든다.

더보기

DynamicArray.cpp

더보기

저작자 표시
신고

'컴퓨터 언어 > C++' 카테고리의 다른 글

예외 처리, 예외에 안전한 코드 만들기  (0) 2012.12.24
예외 처리, 함수 깊숙히  (0) 2012.12.24
예외 처리  (0) 2012.12.21
오버라이딩  (0) 2012.12.20
가상함수를 이용한 다형성 구현  (0) 2012.12.20
다중상속(Multiplex inheritance)  (0) 2012.12.20


티스토리 툴바