아래의 코드는 감기 환자가 코막힘, 재채기, 콧물을 해결하기 위해 각각의 약을 따로 복용하는 상황을 나타내고 있다.
#include <iostream>
using namespace std;
class SinivelCap // 콧물 처치 약
{
public:
void Take() const {cout<<"콧물 처치 완료"<<endl;}
};
class SneezeCap // 재채기 처치 약
{
public:
void Take() const {cout<<"재채기 처치 완료"<<endl;}
};
class SnuffleCap // 코막힘 처치 약
{
public:
void Take() const {cout<<"코막힘 처치 완료"<<endl;}
};
class ColdPatient // 감기 환자 클래스
{
public:
void TakeSinivelCap(const SinivelCap &cap) const {cap.Take();}
void TakeSneezeCap(const SneezeCap &cap) const {cap.Take();}
void TakeSnuffleCap(const SnuffleCap &cap) const{cap.Take();}
};
int main(void)
{
// 각각의 약 객체 생성
SinivelCap scap;
SneezeCap zcap;
SnuffleCap ncap;
// 환자 객체 생성 후, 각각의 약 복용
ColdPatient sufferer;
sufferer.TakeSinivelCap(scap);
sufferer.TakeSneezeCap(zcap);
sufferer.TakeSnuffleCap(ncap);
return 0;
}
여기에서 만약 아래 조건을 가정한다면 어떻게 될까?
1. 코감기는 반드시 콧물, 재채기, 코막힘을 동반한다.
2. 약의 복용 순서가 정해져 있다.
복용의 절차가 번거롭게 느껴질 뿐만 아니라, 각 약 클래스들의 상호관계도 알아야 한다.
캡슐화가 무너지면 객체의 활용이 매우 어려워지고, 클래스의 상호관계가 복잡해지기 때문에 프로그램 전체의 복잡도가 높아진다.
위의 코감기 환자의 약 복용과 관련된 코드를 캡슐화를 진행해보자.
#include <iostream>
using namespace std;
class SinivelCap // 콧물 약
{
public:
void Take() const {cout<<"콧물 처치 완료"<<endl;}
};
class SneezeCap // 재채기 약
{
public:
void Take() const {cout<<"재채기 처치 완료"<<endl;}
};
class SnuffleCap // 코막힘 약
{
public:
void Take() const {cout<<"코막힘 처치 완료"<<endl;}
};
// 콧물, 재채기, 코막힘의 기능을 모두 가진 약
class CONTAC600
{
private:
SinivelCap sin;
SneezeCap sne;
SnuffleCap snu;
public:
void Take() const // 약의 복용 순서가 고정됨
{
sin.Take();
sne.Take();
snu.Take();
}
};
class ColdPatient
{
public:
void TakeCONTAC600(const CONTAC600 &cap) const { cap.Take(); }
};
int main(void)
{
CONTAC600 cap;
ColdPatient sufferer;
sufferer.TakeCONTAC600(cap);
return 0;
}
CONTAC600
클래스를 정의해서 콧물, 재채기, 코막힘에 해당하는 기능을 하나로 통합해주는 약 클래스를 정의했다.
클래스 안에 void Take() const
함수를 정의함으로써 약의 복용 순서 역시 고정되었다.
약의 복용 역시 sufferer.TakeCONTAC600(cap);
이렇게 간결해진 것을 알 수 있다.
캡술화의 범위를 정하기 어렵다.
모든 코감기는 반드시 코막힘, 콧물, 재채기를 동반하는가? 혹은 두통이나 몸살 등을 반드시 동반하지는 않는가?
상황에 따라 캡슐화의 범위는 달라질 수 있으므로, 구체적인 가정과 정보가 필요하다.
캡슐화에는 정보 은닉이 기본적으로 포함된다.
CONTAC600 클래스에서 재채기, 콧물, 코막힘 멤버 변수를 private
변수로 설정하고 복용 함수를 const
함수로 선언하면서 안전하게 감싸고 있다.
<출처 : 윤성우의 열혈 C++ 프로그래밍>
위 책을 공부하며 정리한 내용입니다.