C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 강좌/문서
C++Builder Programming Tutorial&Docments
[91] 왜 소멸자는 virtual 로 만드나?
김태선 [jsdkts] 28425 읽음    2005-12-20 15:59
보통 클래스를 만들면 소멸자를 virtual(가상)함수로 만들게 됩니다.
남들이 다 하닌까.. 따라 하는 사람도 많습니다.
하지만 정확한 이유를 아는 것이 중요합니다.

클래스에서 virtual 함수를 가상함수라고 합니다.
가상함수를 두는 이유는 자신을 상속한 자손 클래스에서 해당 기능을 별도로 구현할때 주로 씁니다.

class TSoccerBall
{
;
virutal void PaintBall();
;
};

위는 축구공을 다루는 클래스라고 가정하고 축구 공을 그리는 부분은 PaintBall() 함수에서 한다고 치십다.
그런데 이 클래스가 그리는 축구공은 2002년형 피파 공인구 입니다. 이를 2006년형 공인구 모양으로 바꾸어
그리고 싶습니다.
물론 TSoccerBall 클래스의 여타 기능은 손댈 필요가 없는 상황입니다.
바로 그런 경우를 대비해서 원 설계자가 필요하면 다시 그리라고 함수를 virtual 로 선언해 놓은 것입니다.

class TSoccerBall2006 : public TSoccerBall
{
;
virutal void PaintBall();
;
virtual ~TSoccerBall2006();
};

이렇게 상속을 받아서 PaintBall() 함수를 새로 만들어 2006형 공으로 그려주면 됩니다.
원래 TSoccerBall  클래스에서는 어떤 상황에서 볼의 모양을 그리도록 내부에서 호출을 하는데
TSoccerBall2006 클래스가 상속받은 후에는 새롭게 만들어진 PaintBall() 함수를 호출하게 바뀝니다.
(물론, 굳이 virtual 로 안해도 이렇게 상속받아 새 공모양을 그리면 되지만, virtual을 쓰게 되면
조상 클래스의 포인트를 가지고도 후손 클래스의 virtual 함수를 부르게 되므로
TSoccerBall 클래스의 객체에서 PaintBall() 을 불러도 2006형 공 모양이 그려지게 됩니다)

이렇게 되면 원래 2002년형 볼을 그리도록 되어 있던 부분은 호출되지 않겠지요.
물론 TSoccerBall::PaintBall(); 로 억지로 호출할 수는 있지만, 새로운 공 모양만을 사용한다면
한번도 호출할 필요가 없어지고 그 코드는 사실 쓸모가 없게 됩니다.
이렇게 되면 이는 필요없는 코드 즉 오버헤드(overhead)가 되는 것입니다.

TSoccerBall2006 클래스는 TSoccerBall의 모든 기능을 이어 받으면서도 공모양만 바꾸었으므로
가상 함수는 정말로 유용한 것이라 아니할 수 없습니다.
그리고 2010년에 또 다른 공모양을 그리라고 새로 만든 PaintBall() 함수도 virtual 로 선언했습니다.

이런 식으로 가상함수를 만드는 것은 오버라이드(override)한다고 합니다.
인자만 다르고 함수 이름이 같은 것을 오버로딩(overloading)이라고 하는 것과 발음은 비슷해도
뜻이 완전히 틀리니 주의 하시기를...

가상함수라는 것은 위에서 잠시 봤듯이 오버헤드를 감수할만큼의 좋은 특징이 있기 때문에
너무나 흔하게 주변에서 접하는 소스에서 virtual 을 볼수 있습니다.

여기까지는 대부분 아시는 사실일 테고요.

다음은 왜 소멸자는 항상 virtual 로 만들까? 하는 문제에 대해 생각해 보겠습니다.
물론 소멸자를 virtual 로 만들지 않는다고 누가 뭐라고하는 사람 없습니다.
어디까지나 플머 마음입니다.

하지만 virtual로 하지 않으면 안되는 이유가 있습니다.
위의 예에서

TSoccerBall2006  *p2006 = new TSoccerBall2006;
TSoccerBall *p = p2006;
와 비슷한 형태로 p 가 자손 객체의 포인트를 가지고 있고
나중에
delete p;
로 객체를 소멸할때
소멸자가 virtual 이 아니면 결코 TSoccerBall2006  의 소멸자는 불려지지 않습니다.
바로 이런 문제 때문에 상속관계에 있고 리소스를 해제해야하는
소멸자는  거의 virtual 로 선언되는 것입니다.

여기서 반드시 알아야 하는 것은 생성과 소멸의 순서입니다.
생성의 과정은 반드시 조상 클래스의 생성자가 먼저 실행되고
소멸의 과정은 virtual 인 경우 자손 클래스의 소멸자가 먼저 실행됩니다.
물론 virtual 이 아니어도 자손의 소멸자가 먼저 실행되지만,
위처럼 조상 클래스 포인트가 자손 객체를 가르키는 경우의 객체 소멸시에도
virtual 인 경우는 소멸자가 안전하게 먼저 불려지게 됩니다.
이 때문에 소멸자는 거의 virtual 을 붙이게 되는 것입니다.

여러분들도 소멸자는 적절하게 상황을 판단해 virtual 을 붙이는게 좋습니다.

또 하나 기억할 것은,
일반 가상함수는 최종적으로 override된 자손의 함수만이 실행되지만
소멸자의 경우는 virtual 일지라도 모든 클래스의 소멸자가 불려진다는 사실을 알아야 합니다.
그러므로, 따로 조상 소멸자의 호출은 필요 없습니다.


너무 간단히 설명해서 초입자 분들은 조금 알아 듣기 힘들지도 모르겠는데
공부하다 보면 무슨 뜻이지 알게 될 것입니다.

그럼..
키프(오병종) [obj55]   2006-05-08 11:54 X
아는것을 베풀려는 맘 감사합니다. 잘읽고 갑니다.
홍환민.행복 [hhshhm]   2006-10-11 15:16 X
잘 읽었습니다. 많이 도움되네요^^
남병철.레조 [lezo]   2007-09-11 20:50 X
면접때 C++ 질문으로 자주 써먹었었는데 생각보다 대답 못하는 분들이 많더라구요...

+ -

관련 글 리스트
91 왜 소멸자는 virtual 로 만드나? 김태선 28425 2005/12/20
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.