생성자, 소멸자, 멤버함수로 똑같이 구성되어 있는 함수가 2개있다. 그중 ChildClass 는 BaseClass 로부터 상속한다.
그냥 보면 재미가 없을테니, 퀴즈형식으로 맞춰 봐도 좋을 듯 하다. printf 문에 1-1 부터 2-3 까지 번호를 부여했다. 각 문제에 대해 printf 문이 출력되는 순서는 어떻게 될까?(소멸자 호출도 중요!!)
1. Quiz 1
2. Quiz 2
3. Quiz 3
4. Quiz 4
BaseClass 의 소멸자 부분(8번째 줄)을 virtual ~BaseClass() 로 바꾸어 virtual 로 선언한 후의 Quiz 3 과 같은 소스.
정답 공개....
1. Quiz 1 - 정답
Constructor of Base Class (1-1)
Constructor of Child Class (2-1)
Member Function of Child Class (2-3)
Destructor of Child Class (2-2)
Destructor of Base Class (1-2)
2. Quiz 2 - 정답
Constructor of Base Class (1-1)
Constructor of Child Class (2-1)
Member Function of Child Class (2-3)
Destructor of Child Class (2-2)
Destructor of Base Class (1-2)
3. Quiz 3 - 정답
Constructor of Base Class (1-1)
Constructor of Child Class (2-1)
Member Function of Base Class (3-3)
Destructor of Base Class (1-2)
4. Quiz 4 - 정답
Constructor of Base Class (1-1)
Constructor of Child Class (2-1)
Member Function of Base Class (3-3)
Destructor of Child Class (2-2)
Destructor of Base Class (1-2)
이중에 그나마 틀리게 되는 부분은 소멸자 부분이다.
3, 4번에서는 BaseClass 로 포인터를 만들고 실제 객체화(instantiation)는 ChildClass 로 되어 있다.
virtual 을 쓰지 않은 3번에서는 본래 포인터의 type 인 Base Class 의 소멸자만 호출되었다는 것이 특징이고,
virtual 을 쓴 4번에서는 바로 ChildClass 로 생성한 것과 마찬가지로 Child, Base 순으로 소멸자가 호출되었다.
사실상 3번의 방법은 사용하면 안된다.
단순히 ChildClass 의 소멸자가 호출되지 않아서가 아니라, 3번의 방법은 메모리 누수가 일어날 가능성이 있다.
즉, 실제로 객체화(instantiation)는 ChildClass 로 되어 있기 때문에 메모리도 ChildClass 로 잡혀 있다. 하지만, 3번의 방법으로는 소멸자가 이 객체를 BaseClass 로 생각하고 메모리를 해제하기 때문에 그 메모리 차이만큼 메모리 누수가 일어난다.
여기서의 특징은 멤버함수는 본래의 BaseClass 의 것으로 호출되었다는 것이다.
ChildClass 멤버함수를 호출하기 위해서는 BaseClass 를
virtual void BaseClass 로 변경하면 된다.
또 하나의 특징은 추상화(Abstraction)인데, C++에서는 abstraction 을 직접적으로 사용하지 않는다. 단지, 위의 BaseClass 의 멤버 함수를 virtual void MemberFunction() = 0; (실제 함수 내용은 있어서는 안된다.) 로 선언을 할 경우 이 BaseClass 자체는 Abstraction Class 가 된다. 이 말은, 이 함수를 실제로 직접적으로 객체화할 수 없고, 다른 클래스를 통해서 상속이 된 후에 사용되어야 한다는 의미이다. 그때 그 Child Class 는 반드시 이 MemberFunction() 함수를 정의시켜야 한다.
사실 위의 내용은 어느정도 C++에 익숙한 사람이라면 다 아는 내용이라 포스팅하기 전에 좀 고민했다. 하지만 일단 내 경우는 Quiz 4 번에서 virtual 로 클래스를 소멸할때
Destructor of Child Class (2-2)
Destructor of Base Class (1-2)
로 두번에 걸쳐 소멸된다는 것은 모르고 있었다. Child 의 소멸자만 호출되는 것으로 알고 있었다.(이것을 몰랐던 이유는, 사실 이것때문에 문제가 된 적이 없기 때문이다. 소멸자에서 하는 메모리 해제도 모두 중복 해제를 고려해서 만들기 때문에 역시 문제가 된적이 없었다.)
마지막으로 위의 내용이나 이것을 넘어선 팁은 Effective C++ 책을 참고하면 좋을듯 하다. 볼만한 관련된 내용들이 많다. 단순히 사용법을 떠나 주의해야 하는 내용들이 담겨 있다. 나중에 이 책에 대해서도 포스팅하고 싶지만, 사실 이 책은 너무 유명해서 굳이 나중에 따로 포스팅을 할만하나.. 생각이 들긴하다.







553933
303
432





댓글을 달아 주세요
3-3 ==> 2-3으로 바꿔주세용 -0-;;
지적 감사합니다~