컴퓨터/프로그래밍2010. 7. 23. 16:35
가상함수라는것이 어떻게 쓰일 수 있는지를 생각해보자. 객체지향 구조에서 클래스의 상속 기능을 이용할 때 이 가상 함수가 많이 사용될 수 있다. 

일반적으로 가상함수는 함수를 선언할 때 제일 앞쪽에 virtual 키워드를 붙여서 선언할 수 있다. 그리고 이함수는 부모객체의 포인터로 자식개체의 함수를 불러올 수 있게 해준다. 보통의 멤버함수는 자식 클래스에서 오버라이딩을 하더라도 부모 객체의 포인터에서 호출하면 부모클래스의 함수가 호출된다. 하지만 가상함수를 쓰게 되면 자식클래스의 함수가 호출이 된다는 것이다. 사실 이렇게만 말하면 무슨 말인지는 잘 모르겠다. 예를 보면 확실히 이해를 할 수 있을 것이다. 

#include <iostream>
using namespace std;

class B
{
public :
  virtual foo(int a)
  {
    cout << "B inside int " << a << endl;
  }
  virtual foo(double a)
  {
    cout << "B inside double " << a << endl;
  }
};

class D : public B
{
public:
  foo(int a// B 에서 오버라이딩한 함수 
  {
    cout << "D inside int " << a << endl;
  }
};

int main(int argc, char **argv)
{
  D d;
  B b, *pb = &d;
  
  b.foo(9);  // B inside int 9
  b.foo(9.5);  // B inside double 9.5
  
  d.foo(9);  // D inside int 9
  d.foo(9.5);  // D inside int 9
  
  pb->foo(9);  // D inside int 9
  pb->foo(9.5)// B inside double 9.5
  
  return 0;
}  


자, 이 예시의 주석만 보더라도 위에서 이야기 했던것이 다 이해가 갈 것이다. 클래스 B가 부모 클래스이고 C는 B에서 상속을 받은 자식 클래스이다. 그리고 B는 객체를 두개 만들었는데 일반 객체 b와 포인터 객체 pb를 선언했고 pb는 D의 객체인 d의 주소값을 받아온다. 이럴 경우에 d, b는 함수를 실행시키면 각각 D,B자체에 선언된 함수가 실행이 된다.(d의 경우 int로 받는 foo(int a) 밖에 없지만 9.5가 들어갈 경우 알아서 int로 형변환이 된다. 그리고 pb는 int값이 들어갈 경우 D(자식)함수가, double값이 들어갈 경우 B의 함수가 실행이 된다. 객체하나로 필요한 D, B의 함수를 다 실행 시킬 수 있다. 만약 virtual로 선언 되지 않았다면 어떻게 될까? 위에 말한대로 B의 함수만 실행 될 것이다.(확실하지는 않다. 안해봤기 때문에..)


추가) 순수 가상함수라는것이 있다. 이것은 함수의 원형만 있고 구현은 없는 가상함수를 이야기 하는 것이다. 
virtual int myclassfunc(int a, int b) = 0
이와 같은 형식으로 함수 원형에 0을 대입시켜서 만들 수 있다. 
이와 같은 순수가상함수를 가진 클래스를 추상클래스라고 하고 추상클래스는 순수가상함수 때문에 객체를 만들 수 없다. 단순히 껍데기 역활은 하는듯 하다. 




Posted by 태씽