C++

가상 함수에서 메서드 호출

khon98 2021. 1. 23. 11:35
#include <iostream>
#include <string>

using namespace std;

// person 클래스
class Person {
    char m_name[32]; // 이름
    int m_num; // 주민번호
public:
    Person(const char *name, int num);
    const char* getName() const { return m_name; }
    int getNum() const { return m_num; }
    virtual void print() const; // 가상 함수
};

// Person 생성자
Person::Person(const char *name, int num) : m_num(num) {
    strcpy(m_name, name);
}

// Person 정보 출력
void Person::print() const {
    cout << " [사람 정보] " << endl;
    cout << " 이름 : " << m_name << endl;
    cout << " 주민번호 : " << m_num << endl;
    cout << " 객체크기 = " << sizeof(Person) << endl;
}

// Student 클래스
class Student : public Person {
    int m_sno; // 학번
    char m_dept[32]; // 소속 학과
public:
    Student(const char* name, int num, int sno, const char* dept);
    int getSno() const { return m_sno; }
    const char* getDept() const { return m_dept; }
    void print() const;
};


// Student 생성자
Student::Student(const char* name, int num, int sno, const char* dept) : Person(name, num), m_sno(sno) {
    strcpy(m_dept, dept);
}

// Student 정보 출력
void Student::print()const {
    cout << " [학생 정보] " << endl;
    cout << " 이름 : " << getName() <<endl;
    cout << " 주민번호 : " << getNum() << endl;
    cout << " 학번 : " << m_sno << endl;
    cout << " 소속 학과 : " << m_dept << endl;
    cout << " 객체 크기 : " << sizeof(Student) << endl;
}

// Employee 클래스
class Employee : public Person {
    int m_eno; // 사번
    float m_wage; // 임금
public:
    Employee(const char* name, int num, int eno, float wage);
    int getEno() const { return m_eno; }
    float getWage() const { return m_wage; }
    void print() const;
};

// Employee 생성자
Employee::Employee(const char* name, int num, int eno, float wage) : Person(name, num), m_eno(eno), m_wage(wage) {
    
}

// Employee 정보 출력
void Employee::print() const {
    cout << " [사원 정보] " << endl;
    cout << " 이름 : " << getName() << endl;
    cout << " 주민번호 : " << getNum() << endl;
    cout << " 사번 : " << m_eno << endl;
    cout << " 임금 : " << m_wage << endl;
    cout << " 객체 크기 : " << sizeof(Employee) << endl;
}

// Professor 클래스
class Professor : public Employee {
    int m_level; // 직급
    char m_dept[32]; // 소속 학과
public:
    Professor(const char* name, int num, int eno, float wage, int level, const char* dept);
    int getLevel() const { return m_level;}
    const char* getDept() const { return m_dept;}
    void print() const;
};

// Professor 생성자
Professor::Professor(const char* name, int num, int eno, float wage, int level, const char* dept) : Employee(name, num, eno, wage), m_level(level) {
    strcpy(m_dept, dept);
}

// Professor 정보 출력
void Professor::print() const {
    cout << " [교수 정보] " << endl;
    cout << " 이름 : " << getName() << endl;
    cout << " 주민 번호 : " << getNum() << endl;
    cout << " 사번 : " << getEno() << endl;
    cout << " 임금 : " << getWage() << endl;
    cout << " 직급 : " << m_level << endl;
    cout << " 소속 학과 : " << m_dept << endl;
    cout << " 객체 크기 = " << sizeof(Professor) << endl;
}

// 테스트
int main(int argc, const char * argv[]) {
    Person A("khon", 1234567);
    Student B("khon01", 1357912, 9512, "가나다라마");
    Employee C("khon02", 1535756, 6543, 1.0e6f);
    Professor D("khon03", 1485623, 8456, 2.0e6f, 2, "기니디리미");
    
    Person *P; // 부모 클래스 타입의 포인터
    
    P = &A; P->print(); cout << endl;
    P = &B; P->print(); cout << endl;
    P = &C; P->print(); cout << endl;
    P = &D; P->print(); cout << endl;
    return 0;
}

 

실행 결과

 [사람 정보] 

 이름 : khon

 주민번호 : 1234567

 객체크기 = 48

 

 [학생 정보] 

 이름 : khon01

 주민번호 : 1357912

 학번 : 9512

 소속 학과 : 가나다라마

 객체 크기 : 80

 

 [사원 정보] 

 이름 : khon02

 주민번호 : 1535756

 사번 : 6543

 임금 : 1e+06

 객체 크기 : 56

 

 [교수 정보] 

 이름 : khon03

 주민 번호 : 1485623

 사번 : 8456

 임금 : 2e+06

 직급 : 2

 소속 학과 : 기니디리미

 객체 크기 = 88

 

 

120행

- Person 클래스 타입의 포인터 P가 Person 타입의 객체를 가리키고, print 멤버 함수를 호출하고 있음

- 당연히 Person 클래스의 멤버 함수를 호출

 

121행

- P가 Student 타입의 객체를 가리키는 경우, P에 대해 print 멤버 함수를 호출하니까 정확히 p가 가리키는 객체의 타입인 Student 클래스의 멤버 함수를 호출하고 있음

 

122, 123행

- 120행과 마찬가지로 p가 가리키는 객체의 타입에 해당하는 멤버 함수를 호출하고 있음

- 가상 함수에 대해서는 포인터 타입의 메서드가 호출되는 것이 아니라 객체 타입의 메서드가 호출됨