Notice
Recent Posts
Recent Comments
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

SYDev

C++ Chapter 07-1 : 상속에 들어가기 앞서 본문

Programming Lang/C++

C++ Chapter 07-1 : 상속에 들어가기 앞서

시데브 2023. 7. 18. 16:03

문제의 제시를 위한 시나리오의 도입

 상속을 제대로 다루기 위해서 상속을 통해 해결할 문제부터 살펴보자.

 

 다음 예제는 OrangeMedia라는 회사가 운영하는 '급여관리 시스템'이라는 가정이다. 회사가 이 시스템을 처음 도입할 때만 해도 직원의 근무형태는 '정규직(Permanent)' 하나였다. 따라서 이 시스템은 정규직 직원 관리를 위한 형태로 설계되었다. 그럼 일단 정규직 직원의 관리를 목적으로 정의된 클래스를 먼저 하나 보도록 하자.

class PermanentWorker
{
private:
    char name[100];
    int salary; // 매달 지불해야 하는 급여액
public:
    PermanentWorker(char * name, int money)
        : salary(money)
    {
        strcpy(this->name, name);
    }
    int GetPay() const
    {
        return salary;
    }
    void ShowSalaryInfo() const
    {
        cout<<"name : "<<name<<endl;
        cout<<"salary : "<<GetPay()<<endl<<endl;
    }
};

 이 회사의 정규직 급여는 입사 당시 정해진다. 따라서 이름과 급여정보를 저장할 수 있도록 클래스를 정의하였다.

 

 다음은 위에서 정의한 PermanentWorker 클래스의 객체를 저장 및 관리하기 위한 클래스로, 객체 저장을 목적으로 하는 배열을 멤버로 지니고 있으며, 저장된 객체의 급여 정보를 출력하기 위한 함수를 멤버로 지니고 있다.

class EmployeeHandler
{
private:
    PermanentWorker* empList[50];
    int empNum;
public:
    EmployeeHandler() : empNum(0)
    { }
    void AddEmployee(PermanentWorker* emp) // 매개변수로 동적할당된 메모리 공간이 올 예정
    {
        empList[empNum++]=emp; // 고용자 List에 emp주소 저장
    }
    void ShowAllSalaryInfo() const
    {
        for(int i=0; i<empNum; i++)
            empList[i]->ShowSalaryInfo(); //객체의 멤버함수
    }
    void ShowTotalSalaryInfo() const
    {
        int sum = 0;
        for(int i=0; i<empNum; i++)
            sum += empList[i]->GetPay();  
        cout<<"salary sum : "<<sum<<endl;      
    }
    ~EmployeeHandler()
    {
        for(int i=0; i<empNum; i++)
            delete empList[i]; // 동적할당된 메모리 공간을 소멸시킴
    }
};

 앞서 정의한 Permanent 클래스는 데이터적 성격이 강하다면 이번에 정의한 EmployeeHandler 클래스는 기능적 성격이 강하다. EmployeeHandler 객체는 프로그램을 구성하는 대표적인 다음 기능들을 처리한다.

  • 새로운 직원 정보의 등록(AddEmployee)
  • 모든 직원의 이번 달 급여정보 출력(ShowAllSalaryInfo)
  • 이번 달 급여의 총액 출력(ShowTotalSalary)

 그리고 이렇게 기능의 처리를 실제로 담당하는 클래스를 가리켜 '컨트롤(control) 클래스' 또는 '핸들러(handler) 클래스'라 한다.

 

 마지막으로 위 두 클래스를 기반으로 작성된 main 함수를 제시하겠다.

int main(void)
{
    // 직원 관리를 목적으로 설계된 컨트롤 클래스의 객체 생성
    EmployeeHandler handler;

    // 직원 등록
    handler.AddEmployee(new PermanentWorker("KIM", 1000));
    handler.AddEmployee(new PermanentWorker("LEE", 1500));
    handler.AddEmployee(new PermanentWorker("JUN", 2000));

    // 이번 달에 지불해야 할 급여의 정보
    handler.ShowAllSalaryInfo();

    // 이번 달에 지불해야 할 급여의 총합
    handler.ShowTotalSalaryInfo();

    return 0;
}

 해당 예제는 언뜻 큰 문제가 없어 보이지만, 모든 소프트웨어 설계에 있어서 중요시 하는 것 중 하나는 다음과 같다.

  • 요구사항의 변경에 대응하는 프로그램의 유연성
  • 기능의 추가에 따른 프로그램의 확장성

  그렇다면 우리가 구현한 예제의 유연성과 확장성은 얼마나 확보되어 있는지 확인해보자.

 

문제의 제시

 우리가 구현한 프로그램을 사용하던 OrangeMedia의 고용형태가 다음과 같이 바뀌었다.

  • 고용직, 급여 : 연봉제, 매달의 급여가 정해짐
  • 영업직, 급여 : '기본 급여 + 인센티브'
  • 임시직, 급여 : '시간당 급여 * 일한 시간'

 이런 변화에 맞춰서 급여 관리 프로그램 또한 수정이 필요하다. 과연 프로그램을 얼마나 수정해야 할까?

 

 우선 새로 늘어난 영업직, 임시직을 의미하는 클래스인 SalesMan, Temporary를 새로 추가해야 할 것이다. 또한 EmployeeHandler 클래스에서도 변화가 일어나야 할 것이다. 우선 SlaesMan, Temporary의 객체를 저장하기 위한 배열을 두 개 추가하고 배열 내부에 객체의 수를 세야 하므로 정수형 변수 멤버 두 개를 추가해야 한다. 추가적으로 AddEmployee 함수도 SalesMan 객체용과 Temporary 객체용으로 각각 추가되어야 하고, 전체 급여정보를 출력하는 나머지 두 멤버 함수는 총 3개의 배열을 대상으로 연산을 진행해야 하므로, 반복문을 2개씩 더 추가해야 한다.

 

 결론적으로는 바뀌지 않는 부분이 거의 없는 수준이다. 좋은 프로그램이기 위해서는 클래스 SalesMan, Temporary가 추가되어도 거의 EmployeeHandler 클래스에 변화가 거의 없게 하는 것이 좋다. 이럴때 우리는 '상속'의 개념을 도입하고자 한다. 이에 대해서는 다음 게시물에서 계속 이야기해보자.

 


  출처 : 윤성우, <윤성우의 열혈 C++ 프로그래밍>, 오렌지미디어, 2010.05.12