자 이번 항목은 클래스의 캡슐화와 정말 밀접하게 관련있는 항목이다.
자 우선 웹브라우저를 나타내는 클래스가 하나 있다고 가정하자. 웹브라우저 클래스라면 멤버함수로 제공하는 것들이 상당히 많을 것이다. 웹브라우저로 다운로드한 임시 저장 캐시를 비우는 함수, 방문한 URL 기록을 없애는 함수, 시스템이 갖고 있는 쿠키를 제거하는 함수 등등이 있을 것이다.
class WebBrowser {
public:
...
void clearCache();
void clearHistory();
void removeCookies();
...
};
하지만 여기서 이 세 작업을 한 번에 하고싶은 사람도 있을 수 있기 때문에 이 세 함수를 모아서 불러주는 함수도 준비해 둘수 있다.
class WebBrowser {
public:
...
void clearEverything();
...
};
물론 이 기능은 비멤버 비프렌드 함수로 제공해도 된다.
void clearBrowser(WebBrowser& wb)
{
wb.clearCache();
wb.clearHistory();
wb.removeCookies();
}
자, 그러면 여기서 어느 쪽이 더 괜찮을까? 멤버? 혹은 비멤버?
자, 앞서 나는 이 항목이 클래스의 캡슐화와 밀접한 관련이 있다고 설명했다. 그렇다면 캡슐화가 잘 되어있을 수록 좋은 설계라는 것은 뭐 다 알것이다. 그렇다면 캡슐화가 잘 되었다는 것은 무엇을 의미할까? 캡슐화가 잘 되었다는 것은 private 영역의 멤버에 접근할 수 있는 기회가 적을 수록 잘 되었다고 한다. 자신의 멤버에 접근할 수 있는 방법이 제한되었다는 것이 그만큼 캡슐화가 잘된것 이기 때문이다. 자, 그러면 보도록 하자. 멤버함수로 선언을 했을 때는 실제론 저 함수안에서 직접적으로 멤버 값을 변경하는 것은 없지만 적어도 함수 안에서 마음만 먹으면 언제든지 접근을 하고 값을 변경할 수 있다. 하지만 비멤버 비프렌드 함수는 절대로 의도적으로라도 private 멤버값에 접근할 방법이 전혀 없기 때문에 그 만큼 캡슐화가 잘 되었다고 할 수 있다.
자, 여기서 한 가지 주의할 점은 비멤버 '비 프렌드'함수 라는 것이다. 만약에 비멤버 프렌드 함수라면 클래스 내부 값에 접근이 가능하므로 반드시 '비 프렌드'이어야 한다. 그러면 이제 비멤버 비프렌드 함수가 더 좋다는 것은 알았다. 하지만 그냥 비멤버 상태로 두면 뭔가 좀 어색한데 c++에서는 네임스페이스를 이용하면 훨씬더 자연스럽게 이것을 만들 수 있다.
namespace WebBrowserStuff {
class WebBrowser { ... };
void clearBrowser(WebBrowser& wb);
...
}
이런식으로 웹브라우저를 의미하는 같은 네임스페이스 안에 비멤버 비프렌드 함수를 넣어두면 정말 자연스럽다. 자, 그런데 여기서 만약 비멤버 비프렌드 함수의 종류가 정말 다양해질 가능성도 있다. 그럴 경우에는 제3의 헤더에 몰아서 선언하는 방법이 있다.
// "webbrowser.h" 헤더
// 웹브라우저에 관련된 핵심 기능이 선언됨
namespace WebBrowserStuff {
class WebBrowser { ... };
...
}
// "webbrowserbookmarks.h" 헤더
// 즐겨찾기 기능과 관련된 함수가 선언됨
namespace WebBrowserStuff {
...
}
// "webbrowserscookies.h" 헤더
// 쿠키 기능과 관련된 함수가 선언됨
namespace WebBrowserStuff {
...
}
이런식으로 편의 함수를 여러 개의 헤더 파일에 나누어 놓으면 확장도 쉬워진다. 그러니 앞으로는 무작정 멤버함수로 선언하기 전에 비멤버 비프렌드 함수는 어떤지 잘 생각해서 고려하도록 하자.
'C++ > Effective C++' 카테고리의 다른 글
항목 25 예외를 던지지 않는 swap에 대한 지원도 생각해 보자 (0) | 2024.01.24 |
---|---|
항목 24 타입 변환이 모든 매개변수에 대해 적용되어야 한다면 비멤버 함수를 선언하자 (0) | 2024.01.22 |
항목 22 데이터 멤버가 선언될 곳은 private 영역임을 명심하자 (1) | 2024.01.21 |
항목 21 함수에서 객체를 반환해야 할 경우에 참조자를 반환하려고 들지 말자 (1) | 2024.01.21 |
항목 20 '값에 의한 전달'보다는 '상수객체 참조자에 의한 전달'방식을 택하는 편이 대개 낫다 (2) | 2024.01.20 |