본문 바로가기
C++

[C++] 객체지향과 클래스에 대해 - 캡슐화(Encapsulation)

by rehtorb_s 2020. 6. 16.

클래스의 접근지정자 그리고 캡슐화(encapsulation)

 

이전 포스팅의 소스코드입니다.

//MobilePhone.h
class CMobilePhone
{
public:
	void Call();		//통화기능 제공
	void Display();		//디스플레이 제공
private:
	bool m_bMic;		//마이크 상태
	bool m_bSpeaker;	//스피커 상태
	bool m_bDisplay;	//디스플레이 상태
};

//MobilePhone.cpp
void CMobilePhone::Call()
{
	m_bMic = true;
	m_bSpeaker = true;
	std::cout << "전화 하다" << std::endl;
}

void CMobilePhone::Display()
{
	//핸드폰이 귀에 가까워진다면
	m_bDisplay = true;
	std::cout << "화면을 켜다" << std::endl;
}

//main.cpp
int main(void)
{
	CMobilePhone phone;	//CMobilePhone 객체 생성
	phone.Call();		//멤버함수 Call() 호출
	phone.Display();	//멤버함수 Display() 호출
	return 0;
}

 

1. 접근지정자란? 

외부에서 클래스 멤버에 접근할 때 접근이 허용되는 범위를 지정하는 키워드 입니다. 위 소스코드의 public, private 그리고 protected가 접근지정자 이죠.

   a) public : 멤버(변수, 함수)가 외부에 공개되어 어디서든 접근이 가능합니다. 

   b) private : 멤버를 비공개로 지정하여 외부로부터 접근을 막습니다. private 멤버에 접근하는 방법은 오로지 해당 클래스의 멤버함수 뿐이죠. 

   c) protected : 멤버를 비공개로 지정하지만 상속 관계에 있는 파생클래스도 접근할 수 있습니다.

 

자! 핸드폰의 특징이나 기능중에 겉으로 드러나지 않아야 하는게 무엇이 있을까요?

전화를 예로들어보죠!

1. 번호를 입력한다.

2. 통화버튼을 누른다.

3. 근처의 기지국과 연결을 시도한다.

4. 상대방과 연결이 되면 통화를 한다.

5. 통화종료를 누른다.

 

이 일련의 과정속에 사용자와 핸드폰 내부에서 컨트롤 하는게 무엇인지 파악해야 합니다.

3번을 제외한 나머지 행위는 모두 사용자가 컨트롤을 합니다.

 

3번은 클래스 내에 구현은 되어있지만 내부적으로만 동작을 하도록 설계 되어있는거죠. 우리가 연결될 기지국을 고를 수도, 통신 시퀀스를 멋대로 할 수 없으니까요.

그럼 수정된 클래스를 볼까요?

 

//MobilePhone.h
class CMobilePhone
{
public:
	void Call();		//통화기능 제공
	void Display();		//디스플레이 제공
private:
	bool Connect();		//기지국에 연결
private:
	bool m_bMic;		//마이크 상태
	bool m_bSpeaker;	//스피커 상태
	bool m_bDisplay;	//디스플레이 상태
};

//MobilePhone.cpp
void CMobilePhone::Call()
{
	if (Connect())
	{
		m_bMic = true;
		m_bSpeaker = true;
		std::cout << "전화 하다" << std::endl;
	}
}

void CMobilePhone::Display()
{
	m_bDisplay = true;
	std::cout << "화면을 켜다" << std::endl;
}

bool CMobilePhone::Connect()
{
	//연결이 되면 true반환, 안되면 false반환
	return true;
}

클래스의 private 영역에 Connect() 함수가 추가됐고, Call()이 Connect()를 호출하네요.

전화를 걸었을때 ( Call() 호출) 연결이 된다면( Connect() 호출) 통화를 시작한다~ 라는 의미죠^^

만약 Connect()함수를 public으로 지정하여 다른 무언가가 아무데서나 호출한다면 그건 문제가 되리라는걸 직감으로 아실거에요.

 

또 한가지 Call() 함수는 private영역에서 선언된 m_bMic, m_bSpeaker의 상태값을 변경하는데요. 이 클래스는 오로지 전화 기능만 있는 핸드폰(2G폰)을 추상화한 것이므로, 마이크와 스피커 기능은 Call() 함수를 호출할때만 활성화를 시킬 수 있습니다. 멤버 변수를 밖에다가 내놓지 않는다는 것이죠.

 

일반적으로 멤버변수는 private 지정자로 정의를 하는데, 클래스 내부의 데이터를 외부에서 멋대로 접근하는 것을 허용치 않기 위함입니다. 그렇게 함으로써 데이터의 안전성, 유효성이 보장되는 것이죠. 만약 private으로 감춰진 멤버 변수에 대한 접근(read & write)을 해야한다면 public 지정자에서 Set(), Get()의 함수형태로 선언 및 정의합니다.

 

이런식으로 말이죠

//MobilePhone.cpp
class CMobilePhone
{
public:
	void SetMic(bool value);
	bool GetMic();
private:
	bool m_bMic;		//마이크 상태
	bool m_bSpeaker;	//스피커 상태
};

void CMobilePhone::SetMic(bool value)
{
	m_bMic = value;
}

bool CMobilePhone::GetMic()
{
	return m_bMic;
}

쉽게 말하자면 접근에 제한을 두는.. 이 방법아니면 너는 접근 못해! 라고 통제하는 건데

이런 제한된 접근 조차도 프로그래머가 잘 판단을 해야겠죠?

 

 

private으로 지정된 멤버에 대한 접근 예시를 보겠습니다.

 

 

똑똑한 visual studio의 Intellisense가 접근불가에러를 띄워주네요. 클래스 내부가 아니면 무조건 외부입니다. 때문에 main문에서 접근이 불가한 것이죠.

 

이제 객체지향의 특징 중 하나인 캡슐화(Encapsulation)가 실현 됐습니다 박수~

 

남은 하나 protected는 다음 포스팅에서 객체지향 특징 중 하나인 상속(Inheritance)와 함께 다루겠습니다. 

protected 지정자 안에 선언 및 정의된 멤버는 해당 클래스와 파생 클래스에서만 접근가능하다는 점만 알아두자고요.


포스팅 내용에 오류가 있거나 지적사항이 있다면 댓글로 달아주세요. 배움을 멈추지 않는 Good Programmer가 되겠습니다. 감사합니다.

댓글