Effective C++/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