일단은 객체의 생성 과정중에 가상함수를 호출 하면 어떤일이 발생하는지 알아 보겠는데, 그전에 객체의 생성과정중 객체 생성 순서를 알아 보도록 하겠습니다.
일반적으로 파생 클래스에서 객체가 생성될때 기본 클래스에서 생성자가 먼저 호출이 됩니다. 그 다음 파생 클래스 생성자 호출 소멸자 호출, 그리고 마지막으로 기본 클래스의 소멸자가 호출되는 순서를 가집니다. 하지만 여기서 기본 클래스에서 가상함수 Call을 호출하고 있다고 가정해 봅시다.
일단 기본 클래스에서 함수를 호출을 했으므로 오버라이딩 하고 있는 Derived 클래스의 Call()함수를 호출하게 됩니다. 하지만 여기서 문제가 있습니다. 바로 호출되는건 Derived 클래스의 Call함수가 아닌 Base 클래스의 Call함수가 호출된다는것입니다. 그래서 아래와 같은 에러가 나옵니다.
앞서 Base 와 Derived 클래스의 생성과정을 얘기 했다시피, Bese 클래스는 Derived 클래스 생성자보다 앞서서 실행되기 때문에 Base 클래스 생성자가 돌아가고 있을 시점에 Derived 클래스 데이터 멤버는 아직 초기화된 상태가 아니기 때문입니다. 이런 초기화 되지 않는 영역을 건드린다는 것은 아주 위험성이 높은 상황이라고 말할 수 있습니다.
그럼 이런 문제에 대한 대처 방법에 대해서 알아 봅시다. 기본 클래스 부분이 생성될때는 가상 함수를 호출한다 해도 기본 클래스의 울타리를 넘어 내려갈 수 없기 때문에 가상 함수를 비가상 함수로 바꾸어 필요한 초기화 정보를 파생클래스 쪽에서 기본 클래스 생성자로 올려주도록 만들어 줌으로써 부족한 부분을 역으로 채운면 되는 것입니다. 무리 없이 출력 되는 것을 볼 수 있습니다.
'Effective C++' 카테고리의 다른 글
항목 11. operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자. (0) | 2010.10.07 |
---|---|
항목 10. 대입 연산자는 *this의 참조자를 반환하게 하자. (0) | 2010.10.06 |
항목 8. 예외가 소멸자를 떠나지 못하도록 붙들어 놓자 (0) | 2010.10.05 |
[EC++] 항목 7. 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자. (0) | 2010.10.05 |
[EC++] 항목 6. 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자 (0) | 2010.09.15 |