본문 바로가기
컴퓨터/C++

c++의 가상함수

by 김짱쌤 2015. 3. 10.

가상함수

1. 가상함수 기본 개념

  • 집고 넘어가는 다형성 : 자식은 부모의 역할을 할 수 있는데, 부모는 자식의 역할을 할 수 없다.
  • 포인터 타입의 양면성 : 포인터가 가르치는 객체의 타입(동적 타입), 포인터가 선언될 당시의 타입(정적 타입)
int* a;
char b = 'c';
a = &b;
//a의 정적 타입은 int, a의 동적 타입은 char
  • 객체 포인터에다 '기본' 함수를 호출하면 정적 타입에 명시된 함수가 호출된다. (정적 바인딩)
  • 객체 포인터에다 '가상' 함수를 호출하면 동적 타입에 명시된 함수가 호출된다. (동적 바인딩)
  • 동적 바인딩을 구현하는 방식은 컴파일러마다 다르지만 일반적으로 vTable으로 구현한다.
    • virtual함수를 생성하면 그 클래스 이하 모든 자식 클래스에게 vPtr을 멤버로 (몰래)생성하고 vTable에 가상함수와 함께 등록한다.
    • 가상함수가 호출되면 호출한 객체(동적 타입)에서 vPtr을 찾아서 vTable의 일치하는 함수를 호출한다.
    • 따라서 포인터가 가르치는 객체(동적 타입)의 함수를 호출할 수 있게 하는 것.
  • 동적 바인딩은 vTable에서 가상함수를 찾는 과정을 거치므로 성능 저하를 야기한다.
//예제 코드
class Parent
{
public:
   void funcStatic(){ printf("부모\n");} //일반함수
   virtual void funcDynamic(){printf("부모\n");} //가상 함수
}

class Child : public Parent
{
public:
   void funcStatic(){ printf("자식\n");}
   virtual void funcDynamic(){printf("자식\n");}
}

Parent* node;
node = Child();
node->funcStatic(); // 정적 바인딩으로 호출되므로 '부모' 출력
node->funcDynamic(); // 동적 바인딩으로 호출되므로 '자식' 출력

2. 가상함수 활용

  • 가상함수의 동적 바인딩 덕분에 다형성을 잘 살릴 수 있음.
void main()
{
     //부모 클래스의 컨테이너에 다양한 자식들을 몰아넣고
     Graphic *ar[10]={
          new Graphic(),new Rect(),new Circle(),new Rect(),new Line(),
          new Line(),new Rect(),new Line(),new Graphic(),new Circle() };
     int i;

     //한꺼번에 드로! 동적 바인딩으로 각 자식 객체에 알맞은 draw가 호출된다.
     for (i=0;i<10;i++) {
          ar[i]->Draw();
     }

     for (i=0;i<10;i++) {
          delete ar[i];
     }
}
  • 라이브러리의 클래스(ex cocos2d-x의 Node)를 상속받는 나만의 클래스를 만들때, 기존의 함수를 재정의하는데 사용된다.
  • 상속받는 클래스의 소멸자에 (필히) 사용된다.
    • 자식 클래스의 소멸자를 가상함수로 만들어 주지 않는다면, 자식 클래스의 인스턴스가 부모클래스 타입의 포인터에 있다면, 소멸될때 부모 클래스의 소멸자가 호출된다.
    • 이때 자식클래스가 부모 클래스와 다른 멤버 변수를 가지고 있고, 그것이 메모리를 동적 할당받아서 만들어 낸 것이라면, 이 멤버 변수가 차지하는 메모리 영역을 해제하는 소멸자가 호출되지 않는다.
    • 따라서 상속을 받는 모든 클래스는 소멸자를 가상함수로 만들어주는 것이 좋다.

3. 순수 가상함수

  • 자식 클래스가 반드시 재정의를 해야하는 함수
//기본 형식
class Graphic
{
public:
     //이런걸 순수 가상 함수라고 부른다.
     virtual void Draw()=0;
};
  • 순수 가상함수가 있는 클래스(추상 클래스)는 인스턴스 생성이 불가능하다. 정의되지 않은 함수가 있기 때문!
  • 추상 클래스는 파생되는 자식 클래스들의 기본적인 형태를 구체화하고, 그 객체들의 집합을 관리하는데 사용된다.


'컴퓨터 > C++' 카테고리의 다른 글

c++ 함수포인터 부터 std::function까지  (0) 2015.03.10
FSM과 State 패턴  (0) 2015.03.10
c++의 여러가지 생성자들  (0) 2015.03.10
c++의 static 변수에 대하여  (0) 2015.03.10