is a / has a

C++ 2021. 1. 11. 18:17

https://modoocode.com/210

 

씹어먹는 C++ - <6 - 2. 가상(virtual) 함수와 다형성>

 

modoocode.com

기반 클래스 = 부모 클래스

파생 클래스 = 자식 클래스

 

 

1. is a

- 모든 상속 관계는 is a라고 볼 수 있음, 이를 뒤 바꾸면 성립되지 않음

- 모든 클래스들의 관계는 is a 로만 표현할 수 없음

- 어떤 클래스들 사이에서는 is a 대신에 has a 관계가 성립되기도 함

 

class Manger(파생 클래스) : public Employee(기반 클래스)

 

- Manager 클래스는 Employee의 모든 기능을 포함한다

- Manager를 Employee라고 봐도 무방

- Manager is a Employee

- Employee는 Manager가 아님

- Manager는 Employee로 부를 수 있지만, Employee는 Manager로 부를 수 없음

 

2. has a

- 자동차는 엔진을 가진다 car has a engine, 자동차는 브레이크를 가진다 car has a brake

 

class car {

 pirvate:

  Engine e;

  Brake b;

}

 

- Employeelist는 Employee와 has a 관계임, employee를 포함하고 있음을 알 수 있음

 

class EmployeeList {

 int alloc_employee; // 할당한 총 직원수

 int current_employee; // 현재 직원 수

 Employee **employee_list; // 직원 데이터

}

 

 

EmployeeList

#include <iostream>

class EmployeeList {
    int alloc_employee; // 할당한 총 직원수
    
    int current_employee; // 현재 직원 수
    int current_manager; // 현재 매니저 수
    
    Employee **employee_list; // 직원 데이터
    Manager **manager_list; // 매니저 데이터
};

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    return 0;
}

위 코드에서 가장 문제 되는 것은 각 클래스 별로 따로 데이터를 보관해야 한다는 것

Employee는 Employee * 가 가리켜야 하고, Manager들은 Manager * 가 가리켜야 함

업 캐스팅은 자유롭게 수행될 수 있음

Employee * 가 Manager 객체를 가리켜도 별 문제가 없다는 것

 

void print_employee_info() {
    int total_pay = 0;
    for (int i = 0; i < current_employee; i++) {
        employee_list[i]->print_info();
        total_pay += employee_list[i]->calculate_pay();
}

employee_list[i]->printf_info()를 하게 되면 무조건 Employee 클래스의 print_info 함수가 호출

employee_list[i]는 Employee 객체를 가리키는 포인터이기 때문에 자신이 가리키는 객체가 Employee 객체라고 생각함

Manager 객체와 Employee 객체 모두 Employee* 가 가리키도록 하였으므로,

만일 employee_list[i] 가 가리키는 것이 Manager 객체 일 때, Manager의 print_info함수가 아니라 

Employee의 print_info함수가 호출되서 다른 결과를 냄

마찬가지로 calculate_pay 함수도 Manager의 calculate_pay 가 호출되어야 하는데 

Employee의 calculate_pay가 호출되어서 틀린 결과가 나옴

 

#include <iostream>
#include <string>

using namespace std;

class Employee {
protected:
    string name;
    int age;
    
    string position; // 직책 (이름)
    int rank; // 순위 (값이 클 수록 높은 순위)
public:
    Employee(string name, int age, string position, int rank)
    : name(name), age(age), position(position), rank(rank) {}
    
    // 복사 생성자
    Employee(const Employee& employee) {
        name = employee.name;
        age = employee.age;
        position = employee.position;
        rank = employee.rank;
    }
    
    // 디폴트 생성자
    Employee() {}
    
    void print_info() {
        cout << name << " (" << position << " , " << age << ") ==> " << calculate_pay() << "만원" << endl;
    }
    int calculate_pay() { return 200 + rank * 50; }
};

class Manager : public Employee {
    int year_of_service;
public:
    Manager(string name, int age, string position, int rank, int year_of_service)
    : year_of_service(year_of_service), Employee(name, age, position, rank) {}
    
    // 복사 생성자
    Manager(const Manager& manager)
    : Employee(manager.name, manager.age, manager.position, manager.rank) {
        year_of_service = manager.year_of_service;
    }
    
    // 디폴트 생성자
    Manager() : Employee() {}
    
    int calculate_pay() { return 200 + rank * 50 + year_of_service; }
    void print_info(){
        cout << name << " (" << position << " , " << age << " , " << year_of_service << "년차) ==> " << calculate_pay() << "만원" << endl;
    }
};

class EmployeeList {
    int alloc_employee; // 할당한 총 직원 수
    int current_employee; // 현재 직원 수
    Employee** employee_list; // 직원 데이터
public:
    EmployeeList(int alloc_employee) : alloc_employee(alloc_employee) {
        employee_list = new Employee*[alloc_employee];
        
        current_employee = 0;
    }
    void add_employee(Employee* employee) {
        // current_employee 보다 alloc_employee가 더 많아지는 경우
        // 반드시 재할당을 해야 하지만 여기서는 최대한 단순하게 생각해서
        // alloc_employee는 언제나 current_employee 보다 크다고 생각함
        // 즉 할당된 크기는 현재 총 직원수 보다 많음
        employee_list[current_employee] = employee;
        current_employee++;
    }
    int current_employee_num() { return current_employee; }
    
    void print_employee_info() {
        int total_pay = 0;
        for (int i = 0; i < current_employee; i++) {
            employee_list[i]->print_info();
            total_pay += employee_list[i]->calculate_pay();
        }
        cout << "총 비용 : " << total_pay << "만원 " << endl;
    }
    ~EmployeeList() {
        for (int i = 0; i < current_employee; i++) {
            delete employee_list[i];
        }
        delete[] employee_list;
    }
};


int main(int argc, const char * argv[]) {
    EmployeeList emp_list(10);
    emp_list.add_employee(new Employee("khon01", 10, "평사원", 1));
    emp_list.add_employee(new Employee("khon02", 20, "평사원", 1));
    emp_list.add_employee(new Manager("khon03", 30, "부장", 7, 12));
    emp_list.add_employee(new Manager("khon04", 40, "과장", 4, 15));
    emp_list.add_employee(new Manager("khon05", 28, "차장", 5, 13));
    emp_list.add_employee(new Employee("khon06", 52, "대리", 2));
    emp_list.add_employee(new Employee("khon07", 24, "인턴", -2));
    emp_list.print_employee_info();

    return 0;
}

전부다 Employee의 print_info와 calculate_pay 함수가 호출되서 원래 결과와 달라짐

'C++' 카테고리의 다른 글

예제1  (0) 2021.01.21
static  (0) 2021.01.12
C++ 문제 풀이  (0) 2021.01.11
소켓 프로그래밍 함수와 Winsock2  (0) 2020.12.17
소켓 프로그래밍의 개요  (0) 2020.12.17
Posted by khon98
,