본문 바로가기
Effective C++

이펙티브(Effective) C++ Item 23 : 멤버 함수보다는 비멤버 비프렌드 함수와 더 가까워지자

by gong재이 2022. 6. 2.
반응형

확장성 있는 설계를 하기 위해 이용할 수 있는 방법은 어떤 것이 있을지에 대한 이야기이다.

클래스의 멤버 함수로 제공하는 방식과 비멤버 비프렌드 함수로 제공하는 방식의 장단점을 살펴보고 인터페이스 설계를 할 때 참고하자.

 

namespace WebBrowserStuff{
    class WebBrowser{
    public:
        void clearCache();
        void clearHistory();
        void removeCookie();
        void clearEverything();
    };

    void clearBrowser(WebBrowser& wb)
    {
        wb.clearCache();
        wb.clearHistory();
        wb.removeCookie();
    }
}

웹브라우저로 캐시, 방문한 url 기록, 쿠키들을 지울 수 있는 함수들이 있다고 하자.

사용자 중에서 3가지 동작을 같이 하고 싶을 때 멤버함수로 제공하는 것이 좋을까? 아니면 비멤버 함수로 제공해주는 것이 좋을까?

 

캡슐화

캡슐화 ↑
밖에서 볼 수 있는 것 ↓
유연성 ↑ 


캡슐화의 정도를 파악하는 기준은 클래스의 멤버 함수 또는 데이터 멤버에 접근할 수 있는 개수가 몇 개인지로 파악하면 된다.
private 데이터멤버의 경우 이에 대한 getter, setter에 해당하는 함수의 개수 + 프렌드 함수의 개수이다.
clearEverything() 으로 한다면 그 함수 내에서는 클래스의 private 데이터 멤버 뿐아니라 멤버 함수까지 사용할 수 있다.
clearBrowser() 의 경우는 private으로 된 데이터 멤버나 멤버함수를 이용할 수 없다. 
즉, 캡슐화 측면에서 비멤버 비프렌드(non-friend) 함수가 더 좋다는 의미이다.

 

주의! 이 삼수가 다른 클래스의 멤버가 될 수 없다는 이야기는 아님.

웹브라우저가 가진 private 멤버의 캡슐화에 영향을 주지 않는 점이 중요한 것.

 

 

패키징 유연성(packaging flexibility)

컴파일의 의존도를 낮추고 웹브라우저의 확장성도 높일 수 있다.

편의 함수

clearBrowser() 함수는 편의상 준비한 함수이다. 이 말은 clearBrowser가 없더라도 사용자 측면에서 clearBrowser 와 똑같은 기능을 할 수 있다는 말이다. 사용자는 clearCache(), clearHistory(), removeCookies() 를 순서대로 불러주기만 하면 된다.

 

이러한 편의 함수들을 나누어 놓는 쉽고 깔끔한 방법은 동일한 namespace 에 속하게 하고 헤더를 따로따로 구성하는 방식이다.

//"webbrowser.h" 헤더 - WebBrowser의 핵심 기능들이 선언
namespace WebBrowserStuff{
    class WebBrowser{...};
}

//"webbrowserbookmarks.h" 헤더
namespace WebBrowserStuff{
    ...
    // 즐겨찾기 관련 편의 함수들
}

//"webbrowsercookies.h" 헤더
namespace WebBrowserStuff{
    ...
    //쿠키 관련 편의 함수들
}

namespace는 여러 개의 소스 파일에 나누어 흩어질 수 있기 때문에 응용도가 높은 클래스들은 위와 같은 방식으로 편의 함수를 구성할 수 있다. 이렇게 헤더파일을 따로 구성하면 필요한 경우에만 헤더파일을 사용해 컴파일 의존성을 쉽게 파악할 수 있다.

 

표준 C++ 라이브러리도 위와 같은 구조로 되어 있다.

std namespace 가 여러 개의 헤더 파일(<vector>, <algorithm>, <memory>) 들로 흩어져 선언되어 있다.

 

이렇게 하면 확장성을 높일 수 있는데 해당 namespace 에 비멤버 비프렌드 함수로 원하는 만큼 편의 함수를 추가해주면 되기 때문이다.

클래스는 그 전체가 한번에 정의되어야 하고 여러 조각으로 나눌 수 없기 때문에 비멤버 비프렌드 함수로 편의 함수를 만드는 것이 확장성에서 유리하다.

반응형

댓글