모든 멤버 변수는 private으로 하는 것이 좋다. 상속 관계에서도 동일하다.

우선 모든 멤버 변수를 private으로 선언하면 문법적 일관성을 유지하는데 좋다.

사용자는 고민없이 무조건 멤버 변수에 접근하기 위해서 괄호를 붙여 접근하면 된다.

어떤 변수는 변수명으로 접근해야 하고 어떤 변수는 함수를 통해 접근해야된다면 사용자 입장에서는 헷갈릴만한 문제이다.

 

또한 해당 private 변수에 접근 권한을 부여할 수 있기 때문에 정교하게 제어할 수 있다. (하기 코드 참조)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class AccessLevels
{
public:
    int getReadOnly() const         { return nReadOnly; } 
 
    void setReadWrite(int value) { nReadWrite = value; }
    int getReadWrite()             { return nReadWrite; }
 
    void setWriteOnly(int value) { nWriteOnly = value; }
 
private:
    int nNoAccess;    //해당 int에는 접근 불가.
 
    int nReadOnly;  //해당 int에는 읽기 전용 접근 가능.
 
    int nReadWrite; //해당 int에는 읽기 쓰기 접근 가능.
 
    int nWriteOnly; //해당 int에는 쓰기 전용 전급 가능.
};
cs

 

이렇게 세밀한 접근 제어는 나름대로의 중요성을 갖고 있다. 어떤 식으로든 외부에 노출시키면 안되는 데이터 멤버들이

꽤 많기 때문이다. 또한 캡슐화를 보다 견고하게 할 수 있다.

 

다른 예를 보자. 하기는 자동차의 속도 값을 모아서 평균을 반환하는 클래스이다.

 

1
2
3
4
5
6
class SpeedDataCollection
{
public:
    void addValue(int speed);    //새 데이터 값 추가.
    double averageSoFar() const//평균 속도 반환.
};
cs

 

averageSoFar 멤버 함수를 구현하는 방법은 2가지가 있다.

 

첫 번째 방법.

 

 -지금까지 수집한 속도 데이터 전체의 평균값을 담는 어떤 데이터 멤버를 클래스 안에 넣어두는 방법.

  averageSofar 함수를 호출할 때마다 이 데이터 멤버의 값을 반환한다.

 

두 번째 방법.

 

 - averageSoFar 함수가 호출될 때마다 평균값을 계산해서 반환하는 방법.

 

첫 번째 방법을 사용하면 SpeedDataCollection 객체의 크가 커지지만(평균값을 유지하기 위한 메모리들이 추가 되기 때문)

averageSoFar 함수의 효율은 좋을 것이다.

두 번재 방법을 사용하면 함수 자체의 속도는 느려지지만, SpeedDataCollection 객체의 크기는 첫 번째보다 작아질 것이다.

 

상황에 따라 어떤 방법을 쓰든 상과없지만 중요한 포인트는 두 방법 모두 "평균값 접근에 멤버 함수를 통하게 한다. (다른 말로

평균값을 캡슐화한다.)"라는 점이다.

 

사용자로부터 데이터 멤버를 숨기면(캡슐화하면), 클래스의 불변속성을 항상 유지하는데 절대로 소홀해질 수 없게 된다.

불변속성을 보여줄 수 있는 통로가 멤버 함수밖에 없기 때문이다. 또한 캡슐화는 현재의 구현을 나중에 바꾸기로 결정할 수 있는

권한을 예약하는 셈이다.

만약 멤버 변수가 public으로 되어있으면 사용자는 이 멤버 변수를 직접 가져다 사용했을텐데... 이 멤버 변수를 수정해야되는 일이

발생하면, 사용자 코드도 죄다 수정을 해줘야하기 때문에 수정 작업에 어려움을 겪게 된다.

그러므로 public 이란 "캡슐화되지 않았다"는 뜻이며 또한 "바꿀 수 없다"라는 의미를 담게 되는 것이다.

 

private은 멤버 함수로 접근하기 때문에 내부적으로 멤버 변수가 바껴도 사용자 코드에서는 수정할 부분이 없다는 얘기이다.

즉, 위의 코드에서 평균을 반환하는 방법이 내부적으로 바뀌더라도 사용자는 averageSoFar 함수를 통해 얻는 Data는 동일하기 때문에

아무런 문제가 되지 않는다는 것이다.

 

protected 또한 public과 다를바가 없다. 외부에서 접근을 못하는 것을 제외하면 캡슐화 측면에서는 public과 동일하다.

상속 관계에서는 멤버 변수를 그대로 가져다 사용할 수 있기 때문에 부모 클래스의 멤버 변수가 수정되면 자식 클래스에 엮여있는

해당 변수들도 전부 수정 작업이 되어야 하기 때문이다.

 

캡슐화의 관점에서 접근 수준은 private와 private가 아닌 나머지 이렇게 둘 뿐이다.

 

2줄 요약

 

 - 데이터 멤버는 private 멤버로 선언하자. 클래스 제작자는 문법적으로 일관성 있는 데이터 접근 통로를 제공할 수 있고,

   세밀한 접근 제어도 가능하며, 클래스의 불변속성을 강화할 수도 있고, 내부 구현의 융통성도 발휘 할 수 있다.

 

 - protected는 public과 똑같다고 생각하자.

 

 

 

 

+ Recent posts