스토리텔링 개발자

[Effective C++] 9. 객체 생성 / 소멸 중 가상 함수 호출 문제 본문

개발/Effective C++

[Effective C++] 9. 객체 생성 / 소멸 중 가상 함수 호출 문제

김디트 2024. 5. 23. 11:37
728x90

항목 9. 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자

 

 

 

파생 클래스에서 호출되는 기본 클래스 생성자 문제
  • 기본 클래스 생성 중엔 가상 함수가 먹히지 않는다.
    • 기본 클래스의 생성자가 호출될 동안, 가상 함수는 절대로 파생 클래스로 내려가지 않는다.
  • 기본 클래스 부분이 생성되는 중엔 객체의 타입이 기본 클래스로 인지된다.
    • 가상함수가 기본 클래스의 것으로 호출된다.
    • 런타임 타입 정보를 사용하는 언어 요소(dynamic_cast, typeid 등)에서도 기본 클래스 타입의 객체로 취급한다.
#include <iostream>
#include <typeinfo>

class A
{
public:
    A(){
        std::cout << typeid(this).name() << std::endl;
    }
};
class B : public A 
{
public:
    B(){
        std::cout << typeid(this).name() << std::endl;
    }
};

int main() {
    new B();
    return 0;
}

// === 출력 ===
// P1A
// P1B
  • 기본 클래스에서는 파생 클래스의 데이터가 아직 초기화되지 않았으므로 없었던 것처럼 취급하는 것이 안전하다.

 

 

 

생성자 호출 순서
  • 기본 클래스 -> 파생 클래스 순으로 호출된다.

 

 

 

생성자나 소멸자에서 가상 함수를 호출하지 않도록 하기
  • 생성자나 소멸자에서 가상 함수를 호출하는지 잡아내는 일이 항상 쉽진 않다.
    • 비가상 함수를 호출했으나, 해당 비가상 함수 내에서 가상 함수가 호출되고 있는 경우
    • 순수 가상 함수가 아닐 때는 기본 클래스 버전 함수가 호출되어 오류 없이 실행 (논리적 오류가 발생한다.)
      • 컴파일도 잘 되고 링크도 잘 되므로 찾아내기 힘들다.
  • 대처 방법
    • 가상 멤버 함수를 비가상 멤버 함수로 바꾸고 파생된 클래스의 생성자들로 하여금 필요한 로그 정보를 생성자로 넘겨야 한다는 규칙을 만든다.
728x90
Comments