[OOP] 가상 함수(Virtual function or Virtual method)

2022. 4. 8. 23:14Programming theory/OOP

    목차

이 글은 이전에 운영하던 깃 블로그에서 옮겨온 글입니다.

 

서론

객체지향 프로그래밍의 대표적인 개념들이 있습니다. 추상화, 캡슐화, 상속성, 다형성, 동적 바인딩

이와 관련된 내용은 추후 다뤄보도록 하고 이번 글에서는 '다형성'에 중점을 둔 가상 함수에 관하여 알아보려 합니다.

왜냐하면 가상 함수는 객체지향 언어의 '다형성'을 가능하게 해 주기 때문이죠.


가상 함수(Virtual function or Virtual method)

 가상 함수란 상속하는 클래스 내에서 같은 형태의 함수를 오버 라이딩(overriding) 할 수 있도록, 임시로 선언해놓은 함수를 말합니다. 즉, '일단 이런 함수가 있으니 상속하는 클래스에서 재정의 해서 써라'라는 것이죠. 단어 그대로 가상의 함수인 것입니다.

예를 들어, 아래와 같은 상황이 있다 가정하겠습니다.

  • 사자, 원숭이, 알파카 등 모든 동물은 자신들의 주식을 먹음
  • 단지 먹는 것이 육식인지 초식인지 잡식인지의 차이일 뿐
  • 행위 자체는 같은데 재료가 다르다고 모든 행위를 다르게 정의해야 하는가?
  • 솔직히 좀 낭비이다
  • 사자, 원숭이, 알파카 등을 '동물'이라는 상위 클래스를 상속받는 자식 클래스로 만들어 줌
  • 행위는 부모에 virtual로 선언하고 각각 자식에서 재정의 하면 되지 않을까?

[그림 1. 클래스 구조 예시]

 

아래의 코드 예시를 보겠습니다.

class Animal { 

 	void move(){ 
    		std::cout « “This animal moves in some way” « std::endl; 
    	} 
    
    	virtual void eat(void) {} 
};

// The class “Animal” may possess a definition for eat() if desired. 
class Llama : public Animal { // The non virtual function move() is inherited but not overridden 
	
 	void eat(void) { 
    		std::cout « “Llamas eat grass!” « std::endl; 
    	} 
};

먹는다는 행위인 void eat() 함수를 Animal class 에서class에서 virtual로 선언하고 자식인 Llama class에서 오버 라이딩해주었습니다. 이런 식으로 객체지향의 다형성을 가능하게 해 줍니다.

 


가상 함수의 작동 원리

사실 가상함수가 무엇이냐 보다는, 어떻게 '다형성'을 가능하게 해주는 것인지 작동원리가 중요하다 생각합니다. 

키포인트는 '가상함수 포인터'와 '가상 함수 테이블'입니다.

 

가상 함수 포인터(__vfptr)는 가상 함수가 선언된 class에 자동으로 생기는 포인터 변수입니다.

여담으로 가상함수가 선언된 클래스는 4byte의 크기가 추가됩니다.
32bit 운영체제 기준, 포인터 변수의 크기를 가지며 64bit 운영체제의 경우는 8byte 입니다.

이 가상함수 포인터는 가상 함수 테이블(vftbl)의 시작 주소를 가리키게 되는데요. 가상 함수 테이블은 실제로 실행될 재정의된 함수들이 맵핑된 테이블입니다. 이 테이블 역시 가상 함수가 선언되고 오버라이드 된 함수가 있다면 컴파일러가 생성하게 됩니다.

그렇습니다. 가상함수 포인터를 타고 가상 함수 테이블로 가서 맵핑된 적절한 함수를 바인딩해서 호출하는 것입니다.
가상 함수가 재정의된 클래스의 인스턴스가 생성될 때, 가상 함수 포인터는 가상 함수 테이블을 가리키게 됩니다.
이 객체가 해당 멤버함수를 호출할 때 가상 함수 테이블에서 찾아서 호출하면, 재정의된 멤버 함수가 호출되는 것이죠.

만약 자식클래스에서 가상 함수를 재정의 하지 않으면, 부모 클래스에 선언된 virtual 함수가 호출됩니다.

 

여담으로, 가상함수가 몇 개가 선언되어있던지 4byte 혹은 8byte 만 추가된다.
가상 함수 테이블만 가리키면 되니까요! (이것도 개발자 기술면접 질문으로 종종 나온다고 합니다.)


리소스 출처

[그림 1] : 위키백과, https://ko.wikipedia.org/wiki/%EA%B0%80%EC%83%81_%ED%95%A8%EC%88%98

 

 

반응형
LIST

'Programming theory > OOP' 카테고리의 다른 글

[OOP]객체지향 5원칙(SOLID)  (0) 2022.04.08