반응형
728x90
반응형

멤버함수 가상함수의 동작 원리

  • 가상함수

객체 포인터가 참조를 할 때, 포인터 연산의 기준으로 두는 것은 실제 가리키는 객체의 자료형이 아니라, 선언된 포인터의 자료형을 기준으로 한다. 그로 인해 포인터 변수의 자료형에 따라서 호출되는 함수의 종류가 달라진다.

이와 같은 상황을 발생하지 않도록 가상함수 라는 문법을 제공.

위 소스에서 포인터 변수의 자료형을 기준으로 판단하여 호출되는 함수를 결정하는 상황을 발생시킬 수 있는 오버라이딩 된 함수들이다. 이러한 오버라이딩 된 함수들을 "가상 함수"로 만듦으로써, 실제 가리키는 객체의 자료형을 기준으로 판단하여 호출 함수를 결정하게 만들 수 있다.

가상함수로 만드는 것은 위의 소스처럼 해당 함수 앞에 "virtual" 키워드를 붙임으로써 완성한다.

함수를 가상함수로 만들게 되면 이를 "오버라이딩 하는" 함수들 또한 virtual 키워드를 붙이지 않더라도 자동으로 가상 함수화 된다.

  • 순수 가상함수, 추상 클래스

클래스 중에는 객체 생성을 목적으로 하지 않는 클래스가 존재한다. 상속을 위한 Base 클래스로서 존재하는 클래스들이 존재하는데, 이를 객체로 생성하게 되는 것은 개발자의 실수이다.

이러한 실수를 방지하기 위해 가상함수를 순수 가상함수로 선언하여 객체의 생성을 방지한다.

순수 가상함수란? 함수의 몸체가 정의되지 않은 함수를 말한다. 이를 포함한 클래스는 불완전한 클래스이기 때문에 객체를 생성하게 되면 컴파일 에러가 발생한다. 이러한 순수 가상함수가 멤버 함수로 포함된 불완전한 클래스를 추상 클래스라고 한다.

 

  • 가상 소멸자

소멸자 또한 가상함수 선언이 된다. Base 클래스를 Derived 클래스가 상속하였을 때, Derived 클래스의 생성자를 호출하고 바디를 실행하기 이전에 Base 클래스 생성자를 호출한다. 이 두 생성자는 멤버 변수의 동적 할당을 수행한다고 가정한다! 이 때, 객체 포인터를 이용하여 객체를 할당하였다면 소멸자 또한 객체 포인터의 자료형을 기준으로 판단하여 경우에 따라서는 Derived 클래스의 소멸자가 실행되지 않을 수 있다.

이를 방지하기 위해서 소멸자에 virtual 키워드를 붙임으로써 해결한다.

  • 다형성(polymorphism)

문장은 같은데 결과는 다른 것을 다형성이라고 한다. ( 동질이상, 열혈 C++ 참고 )
오버라이딩, 순수 가상함수 개념이 다형성에 해당한다. 이는 참조자(레퍼런스) 에서도 똑같이 적용된다.

  • 멤버함수의 진실

멤버 변수는 객체 내에 존재한다. 그러나 사실, 멤버 함수는 객체 안에 존재하지 않는다. 멤버 함수는 사실, 메모리 한 공간에 위치하고, 해당 클래스로 선언되어 생성된 객체들이 이 한 공간에 위치한 멤버 함수들을 공유하는 형태로 존재한다.

  • V-Table

위와 같은 두 클래스는 V Table이라는 가상 함수 테이블을 구성하게 된다. 객체 생성이 되지 않더라도 컴파일러에 의해 가상함수 테이블을 만든다.

위의 예제에 해당하는 가상 함수 테이블은 2개가 다음과 같은 형태로 구성이 된다.

유심히 살펴봐야 할 부분은 Derived 클래스의 테이블인데, 이 테이블에서는 상속을 받은 입장인대도 불구하고, Base::f1의 정보가 존재하지 않는다. 이는 오버라이딩 된 가상 함수의 정보는 존재하지 않고, 유도 클래스의 오버라이딩 한 가상 함수만이 존재한다.

728x90
반응형

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

21 연산자 오버로딩  (0) 2020.09.23
20 다중 상속  (0) 2020.09.22
18 상속과 다형성  (0) 2020.09.15
17 상속  (0) 2020.09.14
16 friend, static, const, mutable  (0) 2020.09.14

+ Recent posts