프로그래밍/C++

[C++] 가상 함수 (virtual function)

갓똥 2019. 11. 26. 23:26
728x90
반응형

1. 함수 오버 라이드 (function override)

#include <iostream>

class Shape {
public:
    void Draw() { std::cout << "Shape::Draw" << std::endl; }
};

class Rect : public Shape {
public:
    void Draw() { std::cout << "Rect::Draw" << std::endl; }
};

int main() {
    Shape s; s.Draw();  // Shape::Draw
    Rect r;  r.Draw();  // Rect::Draw
    
    Shape* p = &r;
    p->Draw();  // ??
}

  ① 함수 오버 라이드 (function override)

    => 기반 클래스가 가진 함수를 파생클래스가 다시 만드는 것

    => 주의 ! overloading과 다른 용어

 

  ② 기반 클래스 포인터로 파생 클래스를 가리킬 때 override 된 함수를 호출 하면

    => C++, C# 등의 언어는 기반 클래스 함수 호출

    => java, swift 등의 언어는 파생 클래스 함수 호출

 


2. 함수 바인딩 (binding)

#include <iostream>

class Shape {
public:
    void Draw() { std::cout << "Shape::Draw" << std::endl; }
};

class Rect : public Shape {
public:
    void Draw() { std::cout << "Rect::Draw" << std::endl; }
};

int main() {
    Shape s;
    Rect r;
    
    Shape* p = &r;
    p->Draw();
}

  ① p->Draw(); 를 어느 함수와 연결할 것인가?

    => 방법1. 컴파일 할 때 결정하는 방법 - static binding

    => 방법2. 실행 할 때 결정하는 방법 - dynamic binding

 

위의 코드를 봐선 p가 Shape를 가리키는걸 알 수 있다.
그럼 아래 코드를 보자.
#include <iostream>

class Shape {
public:
    void Draw() { std::cout << "Shape::Draw" << std::endl; }
};

class Rect : public Shape {
public:
    void Draw() { std::cout << "Rect::Draw" << std::endl; }
};

int main() {
    Shape s;
    Rect r;
    
    Shape* p = &r;
    
    //------------
    int n = 0;
    std::cin >> n;
    if ( n == 1 )
        p = &s;
    //------------
    
    p->Draw();  // ??
}

 

main의 추가된 4줄의 코드를 봤을 때 p는 무엇을 가리키고 있을까?
p는 처음엔 Rect, 실행 시간에 사용자가 1을 입력할 경우는 Shape를 가리키고 1이 아니면 여전히 Rect를 가리킨다.
결국 컴파일러는 컴파일 시간에 p가 무엇을 가리키는지 알 수 없다.

 

  ② C++은 기본적으로 컴파일 할 때 함수 호출을 결정한다. (속도때문)

    => 컴파일러는 컴파일 시간에 실제로 p가 어느 객체를 가리키는지 알 수 없다.

    => 컴파일러가 컴파일 시간에 알고 있는 정보는 p는 Shape*라는 사실밖에 없다.

 

Shape* p = &r; 이 Shape가 아닌 Rect를 가리키므로 Rect의 Draw() 함수를 호출하려면
컴파일 시간에 결정을 하면 안되고, 실행 시간에 결정을 해야 한다.
#include <iostream>

class Shape {
public:
    virtual void Draw() { std::cout << "Shape::Draw" << std::endl; }
};

class Rect : public Shape {
public:
    virtual void Draw() { std::cout << "Rect::Draw" << std::endl; }
};

int main() {
    Shape s;
    Rect r;
    
    Shape* p = &r;
    p->Draw();
}

  ③ 가상 함수 (virtual function)

    => 어느 함수를 호출할지는 컴파일 시간에 하지 말고

    => 실행할 때 결정해 달라는 것

    => 메모리에 있는 객체를 조사한 후 호출

 


3. 정리

728x90
반응형