캡슐화 (Encapusulation)
왜 멤버 변수를 비공개(private
)로 할까?
이전 포스트 public과 private 접근 지정자에서 멤버 변수는 일반적으로 private로 설정한다고 했다. 왜 이렇게 설정하는지 현실 세계에서 비유를 들어보자. TV에는 TV를 끄고 켜기 위한 리모컨이 있다. 이 리모컨에는 버튼과 휠 등의 TV를 조작할 수 있는 인터페이스(interface)를 제공하지만, 리모컨의 내부가 어떻게 구현되어 있는지는 숨겨져 있다. 리모컨의 버튼을 누르면 리모컨 내부에서 어떻게 동작해서 TV를 조작하는지 알 필요가 없다. 인터페이스와 구현의 분리는 이렇게 리모컨의 작동 방식을 이해하지 않아도 리모컨을 사용할 수 있으므로 효과적이다.
비슷한 이유로, 프로그래밍에서도 구현과 인터페이스의 분리는 매우 유용하다.
객체 지향 프로그래밍에서 캡슐화는 객체가 구현된 방식의 세부 정보를 사용자로부터 숨기면서 유지하는 방식이다. 대신 사용자는 객체의 공개 인터페이스를 통해 접근할 수 있다.
캡슐화(영어: encapsulation)는 객체 지향 프로그래밍에서 다음 2가지 측면이 있다: 객체의 속성(data fields)과 행위(메서드, methods)를 하나로 묶고, 실제 구현 내용 일부를 외부에 감추어 은닉한다. -위키백과-
C++에서는 접근 지정자를 통해 캡슐화를 구현한다. 일반적으로 클래스의 멤버 변수(구현 세부 정보)는 private
로 설정하고, 멤버 함수(공개 인터페이스)는 public
으로 설정한다. 클래스의 사용자가 인터페이스를 사용하도록 요구하는 것은 멤버 변수에 대한 직접 접근을 제공하는 것보다 부담스러울 수 있지만, 클래스 재사용성과 유지보수 측면에서 더 많은 이점이 있다.
캡슐화된 클래스는 사용하기 쉽고 프로그램의 복잡성을 줄여준다.
완전히 캡슐화된 클래스를 사용하면, 클래스를 사용하기 위해 공개적으로 사용할 수 있는 멤버 함수와 이 함수의 인수 및 반환 값만 알면 된다. 예를 들어 std::string
, std::array
, std::vector
, std::map
등을 사용하는 데 있어서 클래스가 내부적으로 어떻게 구현되었는지 몰라도 사용할 수 있다. 이렇게 캡슐화는 프로그램의 복잡성을 줄여주고, 실수도 줄여준다. 다른 어떤 이유보다 캡슐화의 핵심 장점이다.
C++ 표준 라이브러리의 클래스는 모두 캡슐화되어있다. 만약 std::string
, std::cout
등이 어떻게 구현되었는지 이해해야지만 사용할 수 있다면 훨씬 더 복잡한 C++가 됬을것이다.
캡슐화된 클래스는 데이터를 보호하고 오용을 방지한다.
전역 변수는 아무나 전역 변수에 접근할 수 있으므로 엄격하게 제어할 수 없어서 위험하다. public
멤버 변수도 같은 이유로 위험하다.
class MyString
{
private:
char* m_string; // we'll dynamically allocate our string here
int m_length; // we need to keep track of the string length
};
위 프로그램에서 두 멤버 변수는 서로 관련이 있다. m_length는 항상 m_string이 보유하는 문자열의 길이와 같아야 한다. 만약 m_length가 public
이라면 누구나 m_string을 변경하지 않고도 문자열의 길이를 변경할 수 있는 문제가 있을 것이다.
또한, 멤버를 실수로 사용하지 못하도록 보호할 수 있다. public
멤버 배열 변수가 있는 클래스를 봐보자.
class IntArray
{
public:
int m_array[10];
};
사용자가 배열에 직접 접근할 수 있는 경우, 만약 배열을 잘못된 인덱스로 접근하면 에러가 발생한다.
int main()
{
IntArray array;
array.m_array[16] = 2; // invalid array index, now we overwrote memory that we don't own
}
그러나 배열을 private로 설정하면 인덱스가 유효한지에 대한 확인을 하는 함수를 만들어 사용자가 강제로 사용하게 만들 수 있다.
class IntArray
{
private:
int m_array[10]; // user can not access this directly any more
public:
void setValue(int index, int value)
{
// If the index is invalid, do nothing
if (index < 0 || index >= 10)
return;
m_array[index] = value;
}
};
번역: 이 포스트의 원문은 https://www.learncpp.com/cpp-tutorial/84-access-functions-and-encapsulation/ 입니다.