아하
검색 이미지
생활꿀팁 이미지
생활꿀팁생활
생활꿀팁 이미지
생활꿀팁생활
꽃다운참매298
꽃다운참매29821.04.23

C/C++ 소멸자 관련 질문드립니다.

c++/c에서 A가 B의 부모 함수일때, A a =new B()와 A a=new A()에서 소멸자가 실행되는 순서가 왜 다른가요? 컴파일시 전자는 A의 소멸자만 나오지만 후자는 B의 소멸자가 나온후 A의 소멸자가 나오길래 궁금합니다.

55글자 더 채워주세요.
답변의 개수
2개의 답변이 있어요!
  • 탈퇴한 사용자
    탈퇴한 사용자21.04.25

    C++에서 객체지향 프로그래밍에 대한 질문을 주셨습니다.
    A가 부모 클래스이고 B가 자녀 클래스이란 것이지요?


    RAII (Resource Acquisition Is Initialization)라는 용어가 있습니다.
    리소스의 획득은 곧 초기화라는 말입니다. C++ 에서 초기화는 생성자가 담당을 하고 있습니다.
    또한 내포된 의미는 객체의 소멸하면 자원이 소멸된다는 것도 내부적으로 암시를 한다고 볼 수 있습니다.
    이때 소멸에 대해 담당하는 것이 소멸자입니다.
    즉, 생성자와 소멸자는 클래스의 자원을 할당하고 정리하는 역할을 담당합니다.

    RAII 에는 어떤 객체에 대한 리소스의 담당은 해당 클래스의 역할이라고 보는 디자인 기법입니다.

    질문에서 처럼 B가 A로 부터 상속 구현을 했을 경우,
    A가 할당하는 리소스는 A가 할당하고 해제를 하는 것이 바람직하다고 볼 수 있습니다.

    위의 질문에서는 소멸자의 순서에 대해서만 언급을 했지만 사실 생성자의 호출 순서는 소멸자의 호출 순서와 반대입니다.
    즉 객체의 생성시에는 부모 생성자가 먼저 호출되고 자녀 생성자가 호출되고
    객체의 소멸 시점에는 자녀의 소멸자가 먼저 호출되고 부모의 소멸자가 나중에 호출이 되기 때문입니다.


  • 질문의 요지는 알겠지만, 명확히 하기 위해 조금 다듬어 보겠습니다.

    A가 B의 부모 함수라고 하셨는데 소멸자에 관해 질문하신 것으로 봐서 부모 클래스 또는 상위 클래스가 맞겠지요.

    A a = new B() 이것은 new 키워드에 의한 생성이므로 포인터 변수로 할당하는 A* a = new B() 이어야 하고,

    A a = new A() 이것은 B 클래스와 아무런 관계가 없으므로 질문의 내용과 같으려면 B* b = new B() 가 맞겠습니다.

    A* a = new B() 에서 B클래스의 객체(인스턴스)를 생성했지만 A클래스 포인터 변수에 할당했기 때문에 delete a 실행 시 A클래스의 인스턴스로 간주되어 실제로는 B클래스의 인스턴스 이지만 A클래스의 소멸자만 호출되게 됩니다.

    B* b new B() 에서는 B클래스의 인스턴스를 생성하고 할당도 B클래스 포인터 변수에 할당했으므로 delete b 실행 시 상속 순서의 역순으로 B클래스 소멸자 실행 후 A소멸자가 실행되는, 쉽게 예측되는 결과로 실행되게 됩니다.

    첫 번째의 경우 처럼 실제로 어떤 클래스의 인스턴스인지와 상관없이 할당되는 변수에 따라 해당 변수의 클래스로 간주된다는 것이 중요한 점 입니다.

    A* a = new B() 로 할당했을 때도 B클래스의 소멸자가 먼저 호출되게 하려면 A클래스의 소멸자를 다음과 같이 가상함수로 선언하면 됩니다.

    virtual ~A();

    이렇게 하면 B클래스이 소멸자도 가상함수를 상속받은 것으로 되어 내부적으로 가상 함수 테이블이란 것을 만들어 관리하기 때문에 나중에 delete a를 실행하게 되더라도 실제 B클래스 인스턴스의 가상 함수 테이블을 참조하여 B클래스의 소멸자를 호출한 다음 A클래스의 소멸자를 호출하게 되어 질문하신 후자의 경우와 같은 결과가 됩니다.