본문으로 바로가기

가상 함수, 가상 테이블, 순수 가상함수

category C++ 2018. 10. 1. 20:14

자바에는 상속이 있다. 추상 메소드를 포함하지않는 일반 클래스를 상속받을 수도 있고 추상메소드가 포함된 추상클래스를 상속받아 재정의하여 상속할 수 도 있다. C++도 객차 지향인 만큼 상속이라는 기능을 제공하는데 그제공하는 방식이 자바와는 조금 상이하다.


우선 자바에서는 부모의 레퍼런스로 자식의 객체를 참조한 후 메소드를 호출하면 너무도 당연하게 자식클래스에서 재정의한 메소드가 호출된다. 그런데 C++에서는 이것이 안된다.그렇다면 어떻게해야 자식클래스에서 오버로딩한 메소드를 호출할 수 있을까?

이떄 사용하는것이 virtual키워드이다. 함수명 앞에 virtual이라는 키워드를 붙이면 해당 함수는 virtual function 즉, 가상함수가 된다. 가상함수를 포함하는 클래스로 객체를 생성시 가상테이블이라는 포인터배열이 생성된다.(꼭 배열로 생성되는 건 아니다. 컴파일러 작성자에 따라서 링크드 리스트를 사용하는 경우도 있다고 한다...)

객체를 생성시 생성되것을 다시한번 생각해보자.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
class A{
   int a;
   virtual void setA(int a){
this->a = a;
   }
}

class B :public A{
   int b;
   virtual void setB(int b){
this ->b = b;
   }
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
}
class설명:
A는 부모 클래스로서 멤버변수 a와 가상함수 setA()를 가지고있다.
B는 자식 클래스로서 멤버변수 b와 가상함수 setB()를 가지고있다.
--------------------------------------------------------------------------------

위에서 설명했듯이 가상함수를 가진 클래스로 객체를 만들 경우 가상테이블이 만들어 진다.
가상 테이블이란 객체에 해당하는 클래스가 가진 가상함수의 주소목록이다. 즉, 함수몸체의 주소를 가진 포인터배열이다.

예를들어 A클래스로 객체를 생성시 멤버변수 a앞에 A클래스에 해당하는 가상테이블의 주소를 가르키는 포인터 vptr이 생긴다.
B클래스또한 마찬가지다.



이런식의 그림이다.

부모클래스 타입의 포인터로 자식을 가르키면 자식의 가상테이블에 존재하는 가상함수를 호출하는 것이다.
반면 자식클래스에서 부모클래스의 가상함수를 재정의 하지않는다면 당연히 부모클래스의 가상함수를 호출한다.
---------------------------------------------------------------------------------
순수 가상함수란 무엇인가?

"순수 가상함수는 추상메소드 이다"
자바를 경험한 사람이라면 이 한 마디로 이해할 수 있을것이다.

명칭만 정의하여 바디는 자식에서 재정의하도록 하기위해 사용한다.
(부모를 상속받은 자식에게 재정의를 강제한다.)

virtual void setA() = 0;<-이런식으로 사용한다.

----------------------------------------------------------
정리

virtual키워드가 붙은 함수를 가상함수라고 한다.
가상함수를 포함하는 클래스로 객체생성시 가상테이블과 가상테이블을 가르키는 포인터가 생성된다.
가상 테이블을 가르키는 포인터는 객체의 멤버변수 앞에 잡히는데, 이것을 통해 같은 명의 함수를 구분하여 동적으로 바인딩한다
순수 가상함수는 자바의 추상클래스이다. 오버라이딩이 강제된다.


+a

가상함수로 가상테이블이 생성되면 당연히 이 가상테이블을 가르키는 포인터가 필요하기 때문에 객체의 메모리가 4byte증가한다.
위의 설명과 같이 복잡한 과정이 있기 때문에 시간이 조금 길어진다.


'C++' 카테고리의 다른 글

상속  (1) 2018.10.01
연산자 함수  (1) 2018.10.01
friend 키워드  (0) 2018.10.01
const  (0) 2018.09.20
상수란?  (0) 2018.09.20