티스토리 뷰

반응형

맴버 함수보다는 비멤버 비프랜드 함수와 더 가까워지자


비 멤버함수로 구현한 것이 캡슐화 정도가 더 좋기 때문이다.

어떤 객체의 데이터에 접근할 수 있는 코드가 적을수록 캡슐화가 잘 되어 있는 것이라 할 수 있다.
외부에서 변경 불가능한 영역이 넓을수록 외부와 관계가 적으며, 그로인해 내부 구현이 바뀌더라도 외부에 많은 영향을 주지 않음.

멤버함수는 객체의 private영역까지 접근할 수 있다. 
그러나 비멤버함수는 public영역 외에는 접근이 불가능하므로, 그 객체의 데이터에 직접적으로 접근할 여지가 줄어든다. 따라서 캡슐화가 멤버함수에 비하여 잘된 것이라 할 수 있음. 

주의할 것은 이러한 비멤버함수의 이점은 비프렌드 함수일 때만 적용된다.
프렌드 함수는 접근권한이 멤버함수와 같으므로 캡슐화 정도도 똑같다. 또한 여기서 '비멤버'함수라는 말은 '해당 클래스의 멤버가 아닌' 함수라는 뜻에서 사용한 것이다. 다른 클래스의 멤버함수로 구현해도 됨.

컴파일 의존도를 들 수 있다.
멤버함수로 기능을 구현하게 되면, 그 기능이 필요없는 사람들도 무조건 그 기능에 대해 컴파일을 할 수 밖에 없다. 그러나 비멤버함수로 구현한 뒤에 이를 몇 개의 헤더파일에 나누어두면, 필요한 기능만 포함하여 컴파일 할 수 있음.

컴파일 의존도와 더불어 확장의 이점도 가지게 된다. 
네임스페이스는 한 파일에 묶지 않고 여러 소스파일에 나뉘어 질 수 있으므로 다른 파일에 속한 관련 기능들도 같은 네임스페이스에 묶어줄 수 있다. 같은 네임스페이스 하에서 계속 비멤버함수로 기능을 추가해주게 된다면 그것이 바로 확장임.

런 식으로 사용자의 입장에서도 확장이 가능하나, 멤버함수는 사용자가 확장할 수 없다. 상속을 통한 확장이 가능하나, 클래스의 설계에 따라 제약이 따르므로 ( 예를 들면 비가상소멸자 등의 상속을 고려하지 않은 설계 ) 불편하다.

 

예제 1

웹브라우저를 나타내는 클래스가 있다고 가정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class WebBrowser
{
public:
    void clearCache();   // 웹브라우저로 다운로드한 파일들을 임시 저장한 캐시를 비우는 함수
    void clearHistory();   // 방문한 url의 기록을 없애는 함수
    void removeCookies(); // 시스템이 갖고 있는 쿠키를 전부 제거하는 함수
    void clearEverything(); // 위의 3 함수를 모아서 호출해주는 함수
};
 
 
//clearEverything()의 비멤버 버전
void clearBrowser(WebBrowser& wb)
{
    wb.clearCache();
    wb.clearHistory();
    wb.removeCookies();
}
 
 
 
 
cs

비멤버 비프렌드 함수는 해당 클래스의 private 멤버에 접근할 수 없기 때문에 멤버 함수보다 더 좋음
private 멤버에 접근할 수 있는 함수가 많아지는 것은 좋지 않음
캡슐화의 원리 때문
사용자 수준에서 얻어낼 수 없는 기능은 비멤버 비프렌드 함수도 얻어낼 수 없기 때문에, 얘들은 있어도 그만 없어도 그만

 

 

예제 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//좋은 방법:
//clearBrowser를 비멤버 함수로 두되, WebBrwserStuff와 같은 네임스페이스 안에 두는 것
namespace WebBrowserStuff
{
    class WebBrowser { . . . };
    void clearBrowser(WebBrowser& wb);
}
//즐겨찾기 기능에만 관심있는 사용자가 쿠키 관련 편의 함수에 대한 컴파일 의존성을 고민할 이유가 없음
//즐겨찾기 관련 편의 함수를 하나의 헤더 파일에 몰아서 선언하고, 쿠키 관련 편의 함수는 다른 헤더파일에 선언하면 깔끔함
"webbrowser.h" 헤더 파일
namespace WebBrowserStuff
{
    class WebBrowser {...};   // 핵심 기능 함수들이 여기에 들어감
}
#include <"webbrowserbookmarks.h">
namespace WebBrowserStuff    // 즐겨찾기 관련 편의 함수들
}
 
#include <"webbrowsercookies.h">
namespace WebBrowserStuff    // 쿠키관련 편의 함수들
}
 
 
cs

 

표준 c++ 라이브러리가 이러한 구조로 되어있음
std 네임스페이스에 속한 모든 것들이 <C++ StandardLibrary> 헤더 같은 것에 모조리 들어가 한 통으로 있지 않음
몇 개의 기능과 관련된 함수들이 수십 개의 헤더(<vector>,<algorithm>,<memory> 등)에 흩어져 선언되어 있음
vector 기능만 필요한 사용자는 #include <vector>만 하면 됨
편의 함수 집합의 확장도 쉬워짐

 

결론

멤버 함수보다는 비멤버 비프랜드 함수를 자주 쓰도록 합시다. 
캡슐화 정도가 높아지고, 패키징 유연성도 커지며, 기능적인 확장성도 늘어납니다

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함