728x90

1. 동적결합(Dynamic Binding)의 개념

프로그램이 실행 중일 , 어떤 함수나 메서드를 호출할 실제로 어떤 코드를 실행할지를 결정하는 것

- 즉, 함수 호출이 어떤 객체나 클래스의 실제 버전을 호출할지 런타임(runtime) 시점에 결정하는 

- 주로 객체 지향 프로그래밍에서 다형성을 구현하는 사용됨

 

1) '프로그램 실행 중'에 객체의 실제 타입을 고려

2) 해당 타입에 맞는 함수나 메서드를 호출

 

- 이를 통해 서로 다른 객체 동일한 함수 또는 메서드 호출하더라도, 객체의 고유한 동작 수행할 있음


2) c++에서 동적 결합을 구현하는 두 가지 주요 메커니즘

 

2-1. 가상함수 (virtual functions)

- 함수 앞에 virtual 키워드를 사용

- 가상 함수는 기본형 클래스에서 선언되고 파생 클래스(derived class)에서 재정의(override)할 수 있는 함수

- 가상 함수를 사용하면 런타임 시에 객체의 실제 타입에 따라 올바른 함수 버전이 호출됨

class Shape {
public:
    virtual void draw() {
        // 기본 구현 }
};

class Circle : public Shape {
public:
    void draw() override {}
};

2-2. 가상테이블 (virtual table)

- 가상 함수를 사용할 때, C++ 컴파일러는 객체에 대한 가상 함수 포인터 테이블을 생성함

- 테이블은 가상 함수의 주소를 저장하고, 실제 함수 호출 시에 테이블을 참조하여 올바른 함수를 호출함

 

void drawShape(Shape* shape) {
    shape->draw(); // 동적 결합
}

int main() {
    Circle circle;
    Square square;

    drawShape(&circle); // Circle 클래스의 draw()가 호출됨
    drawShape(&square); // Square 클래스의 draw()가 호출됨

    return 0;
}

구체적인 예제로 동적 결합 이해하기

 

기초형 클래스의 pointer으로 구성된 포인터 array를 선언

→ 해당 array에 기초형 클래스 Time뿐 아니라, 상속 클래스인 NewTime의 주소값도 저장됨

array의 각 원소에 대해 virtual 메서드인 show()를 실행시켜줌

(show 실행될 때마다, 어떤 class 타입인지 실시간으로 판단해스 해당 타입에 대응되는 virtual 메서드를 실행시킴)

 

time.h

#include<iostream>
using namespace std;

#ifndef FIRE_C_TIME_H
#define FIRE_C_TIME_H

class Time{
private:
    int hours;
    int mins;
public:
    Time();
    Time(int, int);

    /* virtual 통해 가상 메소드 선언 */
    virtual void show(); //가상메소드
    virtual ~Time(); //파괴자 역시 가상 메소드로 선언

    int getHour(){return hours;}
    int getMins(){return mins;}

    Time operator*(int n);
    friend Time operator*(int, Time&);
};

class NewTime : public Time {
private:
    int day;
public:
    NewTime(); //생성자
    NewTime(int, int, int); //생성
    void show();
};

#endif //FIRE_C_TIME_H

time_func.cpp

#include "time.h"

Time::Time(){
    hours = 0;
    mins = 0;}

Time::Time(int h, int m){
    hours = h;
    mins = m;}

void Time::show(){
    cout << hours << "시간 " << mins << "분" << endl;}

Time::~Time(){}

NewTime::NewTime() : Time(){
day = 0;
}

NewTime::NewTime(int h, int m, int d) : Time(h, m) {
day = d;
}

void NewTime::show(){
    cout << day << "일 " << getHour() << "시간 " << getMins() << "분" << endl;
}

main.cpp

#include "time.h"
#include "time_func.cpp"

const int MAX = 3;

int main(){
    Time* times[MAX]; //기초형 Time 클래스의 포인터들이 저장된 배열
    //이곳에 Time 기초형 클래스의 포인터도, NewTime 상속 클래스의 포인터도 담김
    int day;
    int hours;
    int mins;

    for (int i = 0; i < MAX; i++) {
        cout << i + 1 << "번째 원소를 정의합니다." << endl;
        cout << "시간을 입력하십시오." << endl;
        cin >> hours;
        cout << "분을 입력하십시오." << endl;
        cin >> mins;
        char check;
        cout << "일 정보가 있다면 1, 없다면 0을 입력하십시오." << endl;
        cin >> check;
        if (check == '0')
            times[i] = new Time(hours, mins);
        else {
            cout << "일을 입력하십시오." << endl;
            cin >> day;
            times[i] = new NewTime(hours, mins, day);
        }
    }

    for (int i = 0; i < MAX; i++){
        cout << i+1 << "번째 정보입니다." <<endl;
        times[i]->show();
        //show를 virtual로 선언했기 때문에,
        //times: time의 pointer 배열이지만
        //Times이면 Time의 show()가, NewTime이면 NewTime의 show()가 실행됨
    }

    for (int i = 0; i < MAX; i++){
        delete times[i]; //delete의 경우 time형에 대한 delete만 이루어짐
        //NewTime 객체의 경우 제대로 delete되지 않음
        //이를 위해 파괴자 역시 virtual로 선언해야 함

    }

    return 0;}
728x90

+ Recent posts