C++에서 메시지와 함께 예외 발생

Jay Shaw 2023년10월12일
  1. 표준 C++ 예외를 사용하여 메시지와 함께 예외 발생 - 잘못된 인수
  2. 표준 C++ 예외 - 중첩 예외를 사용하여 메시지와 함께 예외 발생
  3. 런타임 오류를 사용하여 C++에서 메시지와 함께 예외 발생
  4. 결론
C++에서 메시지와 함께 예외 발생

이 기사에서는 C++에서 변수 메시지로 예외를 발생시키는 방법을 설명합니다. 예외 throw는 충돌이나 오버플로를 방지하기 위해 프로그램 제어를 전환하는 프로세스입니다.

문제가 발생할 수 있는 프로그램 내부에 예외 throw를 배치하여 실행됩니다. C++에는 몇 가지 예외 처리 키워드가 있지만 이 기사에서는 변수 메시지를 사용하여 예외를 throw하는 방법을 살펴봅니다.

표준 C++ 예외를 사용하여 메시지와 함께 예외 발생 - 잘못된 인수

이 프로그램은 C++의 표준 예외에서 유효하지 않은 인수 예외를 사용하여 변수 메시지와 함께 예외를 발생시킵니다.

패키지 가져오기

이 프로그램은 표준 C++ 예외를 포함하는 stdexcept와 입력 및 출력 작업을 위한 iostream의 두 가지 가져오기 패키지를 사용합니다.

예외를 던지는 방법

이 프로그램은 입력으로 제공된 두 숫자를 비교하는 함수를 정의하고 음수 입력이 발생하면 예외를 발생시킵니다. 여기서는 표준 예외 std::invalid_argument가 사용됩니다.

이 프로그램에서 메소드 compare는 두 개의 정수 값 var_avar_b를 매개변수로 사용하여 정의됩니다. 이것은 if를 사용하여 음수(a, b 또는 둘 다)를 확인하고 그렇다면 예외를 발생시킵니다.

if (var_a < 0 || var_b < 0) {
  throw std::invalid_argument("Negative value encountered");

주요 방법

main 메서드는 try-catch 예외 키워드를 사용하여 유효한 예외를 throw합니다.

예외 처리는 try 블록 내에서 compare 메서드를 호출하여 실행됩니다. 입력 (-1,3)이 음수이므로 try 블록은 인수를 catch 블록으로 보내 변수 메시지와 함께 예외를 발생시키고 메시지를 인쇄합니다.

#include <iostream>
#include <stdexcept>

using namespace std;

int check_neg(int var_a, int var_b) {
  if (var_a < 0 || var_b < 0) {
    throw std::invalid_argument("Negative value encountered");
  }
  return 0;
}

int main() {
  try {
    compare(-1, 3);
  } catch (const std::invalid_argument& e) {
    std::cout << "booh!";
  }
}

출력:

booh!
--------------------------------
Process exited after 0.006709 seconds with return value 0
Press any key to continue . . .

표준 C++ 예외 - 중첩 예외를 사용하여 메시지와 함께 예외 발생

예외는 서로 중첩되어 여러 예외 메시지를 연속적으로 표시할 수 있습니다. 이 섹션의 프로그램은 오류 메시지를 중첩된 예외로 래핑한 다음 각 발생 시 변수 메시지와 함께 예외를 발생시키고 함께 표시합니다.

패키지 가져오기

이 프로그램에서 사용되는 가져오기 패키지는 다음과 같습니다.

  • iostream
  • stdexcept
  • exception
  • string
  • fstream

회원 방법

프로그램에는 print_exception, open_filerun의 세 가지 멤버 함수가 있습니다.

방법 print_exception:

여기에는 std 예외를 포착하는 std::exception& ex와 값 0으로 초기화되는 정수 변수 stage라는 두 개의 공개 매개변수가 있습니다. 메서드 내에서 첫 번째 줄 std::cerrEncountered Exception:이라는 오류 메시지를 인쇄하는 데 사용되지만 std::string(level,'')을 사용하여 중첩 수준에 배치됩니다.

오류 메시지 다음에는 ex.what이 옵니다. 여기서 exstd::exception의 개체이고 ex.what은 발생한 오류에 대한 설명 문자열을 반환합니다.

try 블록은 std::rethrow_if_nested(e)를 사용하여 예외를 throw하지만 std 개체 ex가 중첩된 예외에서 파생되는 경우에만 이 프로그램에서 수행합니다.

catch 블록은 std 개체 nestedException을 사용하여 stage 값을 1로 증가시키면서 재귀적으로 자신을 다시 호출합니다. catch(...) 메서드는 모든 예외를 포착합니다.

void print_exception(const std::exception& ex, int level = 0) {
  std::cerr << std::string(level, ' ') << "Encountered Exception: " << ex.what()
            << '\n';
  try {
    std::rethrow_if_nested(ex);
  } catch (const std::exception& nestedException) {
    print_exception(nestedException, stage + 1);
  } catch (...) {
  }
}

위의 코드에서 일어나는 일은 예외에 대한 설명 문자열을 인쇄하려고 시도한다는 것입니다. 함수가 중첩된 것을 찾으면 보유하고 있는 예외에 대한 설명을 인쇄하기 위해 재귀합니다.

메소드 open_file:

이 함수에는 std::string& s라는 단일 문자열 매개변수가 있어 std::string 개체를 생성하고 여기에 별칭 s를 전송합니다.

try-catch 블록은 파일 읽기를 시도하고 파일을 로드할 수 없을 때 예외를 포착하고 중첩된 함수로 래핑합니다.

void open_file(const std::string& s) {
  try {
    std::ifstream file(s);
    file.exceptions(std::ios_base::failbit);
  } catch (...) {
    std::throw_with_nested(std::runtime_error("Couldn't open " + s));
  }
}

메서드 실행():

void run() 메서드는 try 블록 내에서 open_file 메서드를 호출합니다. catch(...) 블록은 std::throw_with_nested를 통해 발생하는 모든 예외를 포착합니다.

현재 처리 중인 예외와 e를 결합하는 예외를 발생시킵니다.

현재 처리 중인 예외는 외부 예외가 되고 e는 중첩 예외가 됩니다. "run() failed"는 인쇄된 최종 메시지입니다.

void run() {
  try {
    open_file("nonexistent.file");
  } catch (...) {
    std::throw_with_nested(std::runtime_error("run() failed"));
  }
}

메서드 int main():

main 메서드는 try 블록 내에서 run() 함수를 호출하고 catch 블록 내에서 프로그램은 e를 매개 변수로 전달하면서 print_exception 메서드를 호출합니다.

가변 메시지로 예외를 발생시키는 함수를 실행하고, 중첩된 형식으로 포착된 예외를 인쇄하고, 각 예외 발생과 함께 사용자 지정 메시지를 표시합니다.

int main() {
  try {
    run();
  } catch (const std::exception& e) {
    print_exception(e);
  }
}

전체 코드:

#include <exception>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>

void print_exception(const std::exception& ex, int stage = 0) {
  std::cerr << std::string(stage, ' ') << "Encountered Exception: " << ex.what()
            << '\n';
  try {
    std::rethrow_if_nested(ex);
  } catch (const std::exception& nestedException) {
    print_exception(nestedException, stage + 1);
  } catch (...) {
  }
}

void open_file(const std::string& s) {
  try {
    std::ifstream file(s);
    file.exceptions(std::ios_base::failbit);
  } catch (...) {
    std::throw_with_nested(std::runtime_error("Couldn't open " + s));
  }
}

void run() {
  try {
    open_file("nonexistent.file");
  } catch (...) {
    std::throw_with_nested(std::runtime_error("run() failed"));
  }
}

int main() {
  try {
    run();
  } catch (const std::exception& e) {
    print_exception(e);
  }
}

출력:

exception: run() failed
 exception: Couldn't open nonexistent.file
  exception: basic_ios::clear

--------------------------------
Process exited after 0.05326 seconds with return value 0
Press any key to continue . . .

런타임 오류를 사용하여 C++에서 메시지와 함께 예외 발생

사용자 지정 클래스를 사용하여 소스 파일의 경로 및 이 오류가 발생한 줄과 함께 변수 메시지와 함께 예외를 throw할 수 있습니다.

이 프로그램은 사용자 정의 클래스와 매크로를 사용하여 std::runtime_error를 사용하여 설명 문자열에 변수 메시지를 출력합니다.

패키지 가져오기

이 프로그램에는 다음과 같은 4개의 가져오기 패키지가 필요합니다.

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

공개 클래스

이 프로그램은 생성자 클래스를 사용하여 변수 메시지와 함께 예외를 발생시키고 공용 생성자가 std::runtime_error를 사용하여 호출될 때 해당 사용자 정의 메시지를 설명 문자열로 표시합니다.

코드 스니펫의 첫 번째 라인은 my_exception 클래스와 새 runtime_error 객체를 생성합니다. 이와 함께 설명 변수 문자열을 전달하는 데 사용되는 문자열 개체 msg가 전역 범위로 만들어집니다.

생성자 클래스 my_exception은 설명 문자열을 전달하는 std 문자열 객체 arg, 파일 이름을 저장하는 데이터 유형 char의 포인터 객체 *file 및 정수 변수의 세 가지 매개변수로 초기화됩니다. 예외가 발생한 라인을 저장하는 라인.

이 개체가 호출될 때 출력을 표시하기 위해 std::ostringstream을 사용하여 문자열 출력 개체가 생성됩니다. 마지막으로 이 개체는 msg 변수에 저장됩니다.

소멸자 ~my_exception() return msg.c_str();을 사용하여 변수 msg를 null로 끝나는 문자열로 반환합니다.

class my_exception : public std::runtime_error {
  std::string msg;

 public:
  my_exception(const std::string &arg, const char *file, int line)
      : std::runtime_error(arg) {
    std::ostringstream o;
    o << file << ":" << line << ": " << arg;
    msg = o.str();
  }
  ~my_exception() throw() {}
  const char *what() const throw() { return msg.c_str(); }
};

매크로와 예외 던지기

여기서 매크로는 #define throw_line(arg)을 사용하여 정의됩니다. throw_line()을 호출하면 my_exception(arg, __FILE__, __LINE__)이 발생합니다.

메서드 void f()는 매크로 throw_line을 호출하고 Oh no! 메시지를 전달합니다.

#define throw_line(arg) throw my_exception(arg, __FILE__, __LINE__);

void f() { throw_line("Oh no!"); }

주요 방법

메인 메서드는 try 블록 내에서 f() 메서드를 호출하여 변수 메시지와 함께 예외를 발생시킵니다. 그러면 메시지 블록이 my_exception 메서드로 전달됩니다.

catch 블록 내에서 runtime_error 객체 ex가 생성되며 ex.what()을 사용하여 설명 문자열을 호출합니다.

설명 문자열이 호출되면 my_exception 생성자 내부에서 ostream 개체가 호출되고 메시지 변수와 함께 파일 이름 및 오류 줄을 반환합니다.

int main() {
  try {
    f();
  } catch (const std::runtime_error &ex) {
    std::cout << ex.what() << std::endl;
  }
}

전체 코드:

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

class my_exception : public std::runtime_error {
  std::string msg;

 public:
  my_exception(const std::string &arg, const char *file, int line)
      : std::runtime_error(arg) {
    std::ostringstream o;
    o << file << ":" << line << ": " << arg;
    msg = o.str();
  }
  ~my_exception() throw() {}
  const char *what() const throw() { return msg.c_str(); }
};
#define throw_line(arg) throw my_exception(arg, __FILE__, __LINE__);

void f() { throw_line("Oh no!"); }

int main() {
  try {
    f();
  } catch (const std::runtime_error &ex) {
    std::cout << ex.what() << std::endl;
  }
}

출력:

D:\c++\std-exceptions\8.cpp:23: Oh no!

--------------------------------
Process exited after 0.006875 seconds with return value 0
Press any key to continue . . .

결론

이 문서에서는 변수 메시지를 사용하여 예외를 throw한 다음 예외가 throw될 때 메시지를 표시하는 다양한 방법을 설명합니다.

이 문서가 가변 메시지로 예외를 throw하는 방법을 배우고 실제 시나리오에서 사용할 수 있도록 도움이 되었기를 바랍니다.

관련 문장 - C++ Exception