C++/Exception 2021. 3. 22. 00:10

예외 클래스와 상속 (Exception Class and Inheritance)

예외 클래스

  • 예외 상황을 처리할 때 필요한 변수나 함수를 멤버로 가진 클래스

  • 예외 클래스를 사용하지 않은 예제

    #include <iostream>
    
    using namespace std;
    
    class MyArray
    {
      int        data_[5];
    
    public:
      int& operator[] (const int& index)
      {
        if (index < 0 || index >= 5)
          throw -1;
        return data_[index];
      }
    };
    
    void        doSomething()
    {
      MyArray    my_array;
    
      try
      {
        my_array[100];
      }
      catch (const int& x)
      {
        cerr << "Exception " << x << endl;
      }
    }
    
    int            main()
    {
      doSomething();
    }
    
    /* stdout stderr
    Exception -1
    */

  • 예외 클래스를 직접 만들어서 사용하기

    #include <iostream>
    
    using namespace std;
    
    class Exception
    {
    public:
      void    report()
      {
        cerr << "Exception report\n";
      }
    };
    
    class MyArray
    {
      int        data_[5];
    
    public:
      int& operator[] (const int& index)
      {
        if (index < 0 || index >= 5)
          throw Exception();
        return data_[index];
      }
    };
    
    void        doSomething()
    {
      MyArray    my_array;
    
      try
      {
        my_array[100];
      }
      catch (Exception& e)
      {
        e.report();
      }
    }
    
    int            main()
    {
      doSomething();
    }
    
    /* stdout stderr
    Exception report
    */

예외 클래스를 상속해서 사용하기

  • 다형성을 적용하지 않는 경우

    #include <iostream>
    
    using namespace std;
    
    class Exception
    {
    public:
      void    report()
      {
        cerr << "Exception report\n";
      }
    };
    
    class ArrayException : public Exception
    {
    public:
      void    report()
      {
        cerr << "Array exception report\n";
      }
    };
    
    class MyArray
    {
      int        data_[5];
    
    public:
      int& operator[] (const int& index)
      {
        if (index < 0 || index >= 5)
          throw ArrayException();
        return data_[index];
      }
    };
    
    void        doSomething()
    {
      MyArray    my_array;
    
      try
      {
        my_array[100];
      }
      catch (Exception& e)
      {
        e.report();
      }
    }
    
    int            main()
    {
      doSomething();
    }
    
    /* stdout stderr
    Exception report
    */
    • 객체 잘림으로 인해 Exception::report() 함수가 작동한 것을 알 수 있다.
  • 다형성을 적용한 경우 (virtual 키워드 사용)

    #include <iostream>
    
    using namespace std;
    
    class Exception
    {
    public:
      virtual void    report()
      {
        cerr << "Exception report\n";
      }
    };
    
    class ArrayException : public Exception
    {
    public:
      void    report()
      {
        cerr << "Array exception report\n";
      }
    };
    
    class MyArray
    {
      int        data_[5];
    
    public:
      int& operator[] (const int& index)
      {
        if (index < 0 || index >= 5)
          throw ArrayException();
        return data_[index];
      }
    };
    
    void        doSomething()
    {
      MyArray    my_array;
    
      try
      {
        my_array[100];
      }
      catch (Exception& e)
      {
        e.report();
      }
    }
    
    int            main()
    {
      doSomething();
    }
    
    /* stdout stderr
    Array exception report
    */

  • 맨 처음 catch된 부분만 처리된다.

    #include <iostream>
    
    using namespace std;
    
    class Exception
    {
    public:
      void    report()
      {
        cerr << "Exception report\n";
      }
    };
    
    class ArrayException : public Exception
    {
    public:
      void    report()
      {
        cerr << "Array exception report\n";
      }
    };
    
    class MyArray
    {
      int        data_[5];
    
    public:
      int& operator[] (const int& index)
      {
        if (index < 0 || index >= 5)
          throw ArrayException();
        return data_[index];
      }
    };
    
    void        doSomething()
    {
      MyArray    my_array;
    
      try
      {
        my_array[100];
      }
      catch (Exception& e)
      {
        e.report();
      }
      catch (ArrayException& e)
      {
        e.report();
      }
    }
    
    int            main()
    {
      doSomething();
    }
    
    /* stdout stderr
    Exception report
    */
    warning C4286: 'ArrayException &': is caught by base class ('Exception &') on line 44
    • 따로 처리해야 하는 경우에는 더 작은 범위의 클래스를 위에 두면 된다.

      #include <iostream>
      
      using namespace std;
      
      class Exception
      {
      public:
        void    report()
        {
          cerr << "Exception report\n";
        }
      };
      
      class ArrayException : public Exception
      {
      public:
        void    report()
        {
          cerr << "Array exception report\n";
        }
      };
      
      class MyArray
      {
        int        data_[5];
      
      public:
        int& operator[] (const int& index)
        {
          if (index < 0 || index >= 5)
            throw ArrayException();
          return data_[index];
        }
      };
      
      void        doSomething()
      {
        MyArray    my_array;
      
        try
        {
          my_array[100];
        }
        catch (ArrayException& e)
        {
          e.report();
        }
        catch (Exception& e)
        {
          e.report();
        }
      }
      
      int            main()
      {
        doSomething();
      }
      
      /* stdout stderr
      Array exception report
      */

rethrow

  • catch문 내부에서 throw를 한 번 더 사용할 경우, 값을 전달할 때 차이가 존재한다.

    • throw e; 형태로 직접 값을 넘겨줄 경우

      • 객체 잘림이 발생했을 경우 잘린 상태 그대로 넘어간다.
      #include <iostream>
      
      using namespace std;
      
      class Exception
      {
      public:
        void    report()
        {
          cerr << "Exception report\n";
        }
      };
      
      class ArrayException : public Exception
      {
      public:
        void    report()
        {
          cerr << "Array exception report\n";
        }
      };
      
      class MyArray
      {
        int        data_[5];
      
      public:
        int& operator[] (const int& index)
        {
          if (index < 0 || index >= 5)
            throw ArrayException();
          return data_[index];
        }
      };
      
      void        doSomething()
      {
        MyArray    my_array;
      
        try
        {
          my_array[100];
        }
        catch (Exception& e)
        {
          cout << "doSomething ";
          e.report();
          throw e;
        }
      }
      
      int            main()
      {
        try
        {
          doSomething();
        }
        catch (ArrayException& e)
        {
          cout << "Main ";
          e.report();
        }
        catch (Exception& e)
        {
          cout << "Main ";
          e.report();
        }
      }
      
      /* stdout stderr
      doSomething Exception report
      Main Exception report
      */
    • throw; 형태로 값 없이 키워드만 작성할 경우

      • catch한 값을 그대로 다시 throw해서 객체 잘림이 발생하지 않는다.
      #include <iostream>
      
      using namespace std;
      
      class Exception
      {
      public:
        void    report()
        {
          cerr << "Exception report\n";
        }
      };
      
      class ArrayException : public Exception
      {
      public:
        void    report()
        {
          cerr << "Array exception report\n";
        }
      };
      
      class MyArray
      {
        int        data_[5];
      
      public:
        int& operator[] (const int& index)
        {
          if (index < 0 || index >= 5)
            throw ArrayException();
          return data_[index];
        }
      };
      
      void        doSomething()
      {
        MyArray    my_array;
      
        try
        {
          my_array[100];
        }
        catch (Exception& e)
        {
          cout << "doSomething ";
          e.report();
          throw;
        }
      }
      
      int            main()
      {
        try
        {
          doSomething();
        }
        catch (ArrayException& e)
        {
          cout << "Main ";
          e.report();
        }
        catch (Exception& e)
        {
          cout << "Main ";
          e.report();
        }
      }
      
      /* stdout stderr
      doSomething Exception report
      Main Array exception report
      */

'C++ > Exception' 카테고리의 다른 글

C++ 예외 처리의 위험성과 단점  (0) 2021.03.22
C++ 함수 try (Function try)  (0) 2021.03.22
C++ 스택 되감기 (Stack Unwinding)  (0) 2021.03.22
C++ 예외 처리의 기본  (0) 2021.03.22
C++ 예외 처리 (Exception Handling)  (0) 2021.03.22