Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ 생성자에서 예외 발생시키기: 핵심 개념과 예제

C++에서는 생성자 내부에서도 예외(exception)를 던질 수 있습니다. 이 글에서는 C++ 생성자에서 예외를 발생시키는 방법을 의사코드와 실제 예제를 통해 살펴보겠습니다.

핵심 개념

생성자는 반환값이 없기 때문에, 객체 생성 과정에서 오류가 발생했을 때 예외를 던지는 것이 가장 일반적인 오류 보고 방식입니다. 여기서 중요한 규칙이 하나 있는데, 생성자에서 예외가 던져지면 해당 객체의 소멸자는 호출되지 않습니다. 반면, 이미 완전히 생성된 다른 객체들은 스택 풀기(stack unwinding) 과정에서 자동으로 소멸됩니다.

알고리즘

클래스 설명 및 의사코드:

시작
    sample1 클래스를 선언한다.
        sample1의 생성자를 선언한다.
            "Construct an Object of sample1"을 출력한다.
        sample1의 소멸자를 선언한다.
            "Destruct an Object of sample1"을 출력한다.
    sample2 클래스를 선언한다.
        sample2의 생성자를 선언한다.
            정수형 변수 i를 선언한다.
            i를 7로 초기화한다.
            "Construct an Object of sample2"를 출력한다.
            i를 throw하여 예외를 발생시킨다.
        sample2의 소멸자를 선언한다.
            "Destruct an Object of sample2"를 출력한다.
    try 블록:
        sample1 클래스의 객체 s1을 선언한다.
        sample2 클래스의 객체 s2를 선언한다.
    catch(int i)
        "Caught"를 출력한다.
        변수 i의 값을 출력한다.
끝.

예제 코드

#include <iostream>
using namespace std;
class Sample1 {
   public:
      Sample1() {
         cout << "Construct an Object of sample1" << endl;
      }
      ~Sample1() {
         cout << "Destruct an Object of sample1" << endl;
      }
};
class Sample2 {
   public:
      Sample2() {
         int i = 7;
         cout << "Construct an Object of sample2" << endl;
         throw i;
      }
      ~Sample2() {
         cout << "Destruct an Object of sample2" << endl;
      }
};
int main() {
   try {
      Sample1 s1;
      Sample2 s2;
   } catch(int i) {
      cout << "Caught " << i << endl;
   }
}

실행 결과

Construct an Object of sample1
Construct an Object of sample2
Destruct an Object of sample1
Caught 7

결과 분석

실행 결과에서 주목해야 할 세 가지 포인트가 있습니다.

  • s1은 정상적으로 소멸됩니다. Sample2의 생성자에서 예외가 발생하는 시점에 Sample1 객체 s1은 이미 완전히 생성된 상태입니다. 따라서 스택이 풀리면서 s1의 소멸자가 자동으로 호출됩니다.
  • s2의 소멸자는 호출되지 않습니다. Sample2의 생성자가 예외를 던졌기 때문에 객체 생성이 완료되지 않았습니다. C++에서는 생성이 완료되지 않은 객체의 소멸자를 호출하지 않으므로, "Destruct an Object of sample2" 메시지는 출력되지 않습니다.
  • catch 블록이 예외를 처리합니다. main 함수의 catch(int i) 블록이 생성자에서 던진 정수 값 7을 받아 "Caught 7"을 출력합니다.

이처럼 생성자에서 예외를 활용하면 객체 초기화 실패를 명확하게 전달할 수 있으며, 이미 생성된 객체들은 스택 풀기를 통해 안전하게 해제됩니다. 다만 생성자 내부에서 직접 할당한 자원(동적 메모리 등)은 스마트 포인터나 RAII 기법으로 관리해야 메모리 누수를 방지할 수 있다는 점을 기억하세요.