[C++] 항목 22: 데이터 멤버가 선언될 곳은 private 영역임을 명심하자
카테고리: Cpp
태그: Cpp
이 글은 아래의 책을 자세히 정리한 후, 정리한 글을 GPT에게 요약을 요청하여 작성되었습니다.
이펙티브 C++ 제3판, 스콧 마이어스 저자, 곽용재 번역
📦 4. 설계 및 선언
👉🏻 항목 22: 데이터 멤버가 선언될 곳은 private 영역임을 명심하자
데이터 멤버를 private
에 두어야 하는 이유는 다음과 같다:
- 문법적 일관성
- 세밀한 접근 제어
- 캡슐화(encapsulation)
✅ 문법적 일관성
- 데이터 멤버가
private
에만 존재한다면, 모든 접근은 반드시 public 멤버 함수를 통해서만 이루어진다. - 이로 인해 “직접 접근해야 할까, 함수로 접근해야 할까?” 하는 고민이 사라진다. → 접근 방식에 대한 일관성이 생긴다.
✅ 세밀한 접근 제어
데이터 멤버가 public
에 선언되면:
class AccessLevels {
public:
int value;
};
- 외부 누구나
value
에 대해 읽기와 쓰기 모두 가능하다. - → 접근 제어가 불가능하다.
하지만, 멤버를 private
에 선언하고, 함수로 접근을 제어하면:
class AccessLevels {
public:
int getReadOnly() const { return readOnly; }
void setWriteOnly(int value) { writeOnly = value; }
void setReadWrite(int value) { readWrite = value; }
int getReadWrite() const { return readWrite; }
private:
int noAccess; // 접근 불가
int readOnly; // 읽기 전용
int writeOnly; // 쓰기 전용
int readWrite; // 읽기/쓰기
};
- 읽기 전용, 쓰기 전용, 읽기/쓰기 등 다양한 세밀한 제어가 가능하다.
- 단순히 접근을 막는 걸 넘어서, 의도에 맞는 명확한 인터페이스 제공이 가능하다.
✅ 캡슐화(encapsulation)
class SpeedDataCollection {
public:
void addValue(int speed); // 값을 추가
double averageSoFar() const; // 평균 계산
...
};
👉 averageSoFar의 내부 구현 방식은 두 가지 가능
addValue
를 호출할 때마다 평균을 갱신해두고,averageSoFar
는 그 값을 반환.averageSoFar
호출 시, 그때 평균을 계산.
→ 어떤 방식을 선택하든 외부에서는 차이가 없다.
→ 내부 구현을 자유롭게 바꿀 수 있는 여지를 확보하게 된다.
👉 캡슐화를 통해 얻는 이점
- 클래스의 불변속성(invariant) 을 유지할 수 있다.
- 나중에 내부 구현을 변경해도, public 인터페이스가 변하지 않으면 외부 코드에 영향이 없다.
✅ protected는 public과 다를 바 없다
protected
는 겉보기엔 더 안전해 보이지만, 파생 클래스에서 마음대로 접근 가능하므로 실질적으로는public
과 유사하다.- 누군가가
protected
멤버에 의존하는 코드를 작성하면,
public
멤버처럼 변경 시 파급 효과가 클 수밖에 없다.
→ 캡슐화 관점에서 쓸모 있는 접근 제어는 결국 private
와, private
이 아닌 나머지 둘 뿐이다.
🧐 정리
- 데이터 멤버는
private
로 선언하자. 다음과 같은 이점이 있다:- 문법적 일관성을 확보할 수 있다.
- 세밀한 접근 제어가 가능하다.
- 내부 구현을 숨기고, 변경 가능성을 열어두는 캡슐화가 가능하다.
protected
는public
보다 결코 더 안전하지 않다.
→ 외부 의존성이 많아지면, 역시나 변경에 취약하다.
댓글남기기