[Effective C++] 항목23 : 멤버 함수보다는 비멤버 비프렌드 함수와 더 가까워지자

Jangmanbo·2023년 4월 23일
0

Effective C++

목록 보기
23/26
class WebBrowser {
public:
	...
    void clearCache();	// 웹 브라우저로 다운로드한 파일을 임지 저장한 캐시를 비우는 함수
    void clearHistory();	// 방문한 URL의 기록을 없애는 함수
    void removeCookies();	// 시스템이 갖고 있는 쿠키를 전부 제거하는 함수
    ...
}

WebBrowser에 선언한 3가지 함수의 동작을 한 번에 하는 함수 clearEverything을 만들어보자.

1. 멤버 함수

class WebBrowser {
	...
	void clearEverything();	// clearCache, clearHistory, removeCookies를 호출
}

2. 비멤버 함수

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

당연히 멤버 함수가 더 낫다고 생각하겠지만 이러한 경우 비멤버 함수를 채택해야 한다.

비멤버 함수를 사용해야 하는 이유

1. 데이터 캡슐화

객체 지향 법칙에 따르면 할 수 있는 만큼 데이터를 캡슐화해야 한다. 그렇다면 당연히 멤버 함수가 더 좋다고 생각하겠지만, 오히려 멤버 버전인 clearEverything이 비멤버 버전 clearBrowser보다 캡슐화 정도가 떨어진다.

캡슐화 정도가 늘어난다는 것은 그만큼 밖에서 볼 수 있는 것들이 줄어든다는 것이고 그것들을 바꿀 때 필요한 유연성이 커진다. 변경하면서 영향을 줄 수 있는 범위가 변경된 것을 볼 수 있는 것에 한정되기 때문이다. 따라서 어떤 데이터를 접근하는 함수가 많을수록 그 데이터의 캡슐화 정도는 낮다.

private 데이터 멤버의 경우 접근할 수 있는 함수의 개수의 예측이 쉽다(항목 22). 해당 클래스의 멤버 함수 및 프렌드 함수만 접근할 수 있다.

그렇다면 똑같은 기능을 제공하는 함수를 멤버 함수로 쓸 것인지, 비멤버 비프렌드 함수를 쓸 것인지는 고민할 필요가 없이 후자이다. 비멤버 비프렌드 함수는 어떤 클래스의 private 멤버에 접근할 수 있는 함수의 개수를 늘리지 않기 때문이다.

1. 다른 클래스의 멤버함수

비멤버 비프렌드 함수여야 한다는 말이 어떤 클래스의 멤버가 될 수 없다는 의미는 아니다. 따라서clearBrowser다른 유틸리티 클래스의 정적 멤버 함수로 만들어도 된다.

2. 네임스페이스

clearBrowser를 비멤버 함수로 두되, WebBrowserStuff와 같은 네임스페이스 안에 둘 수도 있다.

namespace WebBrowserStuff {
	class WebBrowser { ... };
    void clearBrowser(WebBrowser& wb);
    ...
}

네임스페이스는 클래스와 달리 여러 개의 소스 파일에 나뉘어 흩어질 수 있다. 따라서 clearBrowser와 같은 편의 함수는 네임스페이스로 제공하는 것이 좋다.

WebBrowser처럼 응용도가 높은 클래스는 clearBrowser같은 편의 함수가 많을 것이다. 즐겨찾기, 인쇄, 쿠키 관리 등등이 이에 해당한다.
일반적인 사용자의 경우 이러한 기능 중 몇몇에만 관심이 있을 것이기에, 이를 깔끔하게 나누기 위해서 즐겨찾기 편의 함수들을 즐겨찾기 헤더 파일에, 쿠키 관리 편의 함수들은 쿠키 관리 헤더 파일에 선언하면 좋다.

// webbrowser.h 헤더
// WebBroswer에 관련된 핵심 기능 선언
namespace WebBrowserStuff {
	class WebBrowser { ... };
    ...			// 핵심 기능 함수 (거의 모든 사용자가 사용할 함수) ex. clearBroswer
}

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

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

실제로 표준 C++ 라이브러리가 이러한 구조로 구성되어 있다. std 네임스페이스에 속한 함수들이 수십 개의 헤더(<vector>, <algorithm>, <memory>, ...)에 흩어져 선언되어 있다.

... 추가예정

2. 패키징 유연성

비멤버 함수를 사용하면 WebBrowser 관련 기능을 수성하는 데 있어서 패키징 유연성이 높아지고, 따라서 컴파일 의존도를 낮추며 WebBroswer의 확장성도 높일 수 있다.


정리

  • 비멤버 비프렌드 함수를 자주 사용하자
    • 캡슐화 ↑
    • 패키징 유연성 ↑
    • 기능적인 확장성 ↑

0개의 댓글