이번 항목은 C++ 에서 있어 뺄수 없는 가상성에 대한 논쟁이다. 가상성도 인터페이스의 캡슐화를 통하여, 내부 구현 상태를 숨기고 보호하는데, "가상성"을 제대로 쓰고 있는가? 에 대한 이야기를 시작으로, "어떻게" 가상성을 이용하고 있는가? 로 하여, "접근 지시자(access specifier)"를 적절하게 사용하는 방법에 대해서 집중적으로 말한다.


1 ) 기반 클래스 소멸자에 대한 "흔한 조언"은 무엇인가?

a. 가상 함수는 비공개로 해야 한다.

b. 소멸자는 가상 소멸자여야만 한다.


이 "흔한 조언"들을 따져보자.


a. 가상 함수는 비공개로 해야 한다.

나는 이럴 때 이런 질문을 한다. "어떻게 때문에, 이렇게 해야 하는가?" 일반적으로 나는 가상 함수는 공개 인터페이스와 함께 사용 하고 있었다. 왜냐하면, 공개 인터페이스 자체가 특정 일을 처리하도록 만들어 두었기 때문이다.

물론 "단순한 공개 인터페이스"라면, 이렇게 하는게 더 편할 것이다. 하지만, 공개 인터페이스가 가상 함수라는 것은 그 함수에 "공개 인터페이스 + 가상성"을 함께 부여해야 했다는 것을 의미한다.

여기서 이 함께 부여 했다는 것은 "객체지향 관점"에서 보았을 때, 미묘하게 거슬리는 부분이 있다. 바로, 가상 함수로써의 구현부와, 공개된 인터페이스 구현부가 같이 있어야 한다는 것이다.

이것은 한두개의 클래스를 만들 경우에 크게 문제가 되지 않는다. 하지만, 3만개의 클래스와 10만개의 멤버 함수를 만들어야 하는 거대 프로젝트일 경우에는 어떻게 될까?

프로그램의 유지보수는 끈임없이 해야 할 것이고, 관리적인 측면 때문에, 가상성에 대해서 하나의 일관된 규칙이 필요하게 될 것이다.

예상데로 이런 일을 겪은 회사가 있으니, 바로 "마이크로 소프트"이다. 각종 API 들을 다 모아 두면, 관리가 되지 않으니 "객체지향"을 썼을 것이고, 자연스럽게 "가상성"에 대해서 고심하게 되었을 것이다. 그래서 "마이크로 소프트"사에서 "설계지침" 한가지를 내걸었는데 다음은 인용 문이다.

"커스텀화는 보호된 메서드들을 통해서 제공하는 것을 권장한다. 이것은 컴스텀화가 항상 상속을 하고, 가상함수의 재정의 만으로도 가능하케 해주기 때문이다." <-- 물론 내 식대로 인용했다.  자세한 내용은 Net Framework(WinFx)Design Guidelines, 내부 초안, 2004년 1월을 참조 하라고 한다.

이것은 "Template Method Pattern" 인데, 허브셔터는 "가상성"에 대해 초점을 둔 대안이므로, 비가상 인터페이스(Nonvirtual Interface, NVI)패턴이라 부르고 싶다고 했다.

코드를 한번 봐보자.


9 라인의 함수는 내부적으로 12, 13 라인의 함수를 호출하여, 9라인을 구현한다. 이 구현부는 가상성이 있기 때문에, 유저 스스로가 커스텀화 할 수 있다.

이렇게 만드는 것은 Process 함수는 "공개 인터페이스"만을 제공 하고, DoProcessPhase1, DoProcessPhase2 는 가상성을 제공하는 것을 의미한다.

이제 나중에 Widget 함수를 상속하게 되었을 때, 비가상함수는 나두고, 오로지 가상함수만을 재정의 함으로써, 보다 편한 리펙토링이 가능하게 된다.

물론 무조건 사용하라. 는 무리가 있다. 그래서 "이렇게 할 수 있다면, 이렇게 하는 것을 권장 한다"


b. 소멸자는 가상 소멸자여야만 한다.

이 말은 반은 맞고 반은 틀린 말이다. 기본적으로 다형적으로 삭제할 객체라가 아니라면 소멸자에 가상성을 부여할 필요는 없다.

하지만, 다향성은 사용하되, 삭제는 하지 않는다는것은 너무도 실수를 잘 할 하는 요령을 가르쳐 주는것과 같으니, 이 또한 문제이다. 그렇기 때문에, 이 "흔한 질문"은 다음과 같이 고쳐야 할 것 같다.

기반 클래스 소멸자를 다형적 삭제를 사용을 한다면, 소멸자는 공개 + 가상성을 갖어야 한다. 만약, 다형적 삭제를 사용 하지 않는다면, 소멸자는 비가상 + protected 로 제공해야 한다.

이는 다형적으로 사용 되지 않을 때, 다형적 삭제를 시도하게 되었을 경우, 컴파일 타임에 오류를 벹어내게 하기 때문이다.


총평

이는 절대적이지 않다. 일반적으로 이렇다는 것일 뿐이라고, 책에서 말하고 있다. 경우에 따라서 막 짜는게 더 편할 수 있지만, 그 막짜는 것이 후회 될 때, 울어야만 하는 것을 알아야 될 듯 싶다. : )


posted by 농사를 짓는 게임 프로그래머 최익필

댓글을 달아 주세요

  1. 지나가는 2009.01.18 17:31 신고  Addr  Edit/Del  Reply

    최익필님께서 올려주신 자료 덕분에 공부 잘 하고 있는 한 학생입니다.
    다름이 아니라, 블로그에 SyntaxHighlighter를 설치했는데요
    설치하고 보니 메뉴나 달력의 폰트 크기가 커지더군요; 어떻게 수정해야 할지 난감해서
    도움을 구하고자 합니다. 답변 주시면 감사하겠습니다.