씹어먹는 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 |