가상 함수 (Virtual Function)
가상 함수는 특별한 멤버 함수입니다.
이를 사용하면 부모 포인터형으로 실제 인스턴스가 선언될 때의 자료형(자식)의 함수를 호출할 수 있습니다.
가상 함수를 지정하면 클래스는 해당 함수를 바로 연결하는 것이 아니라
인스턴스에 함수의 연결정보를 구성하고 이를 통해 함수를 호출하게 됩니다.
가상 함수로 지정할 때는 함수의 앞에 virtual 키워드를 붙입니다.
가상 함수를 가지는 부모로부터 파생하는 클래스의
동일 규격의 함수(오버라이딩)는 별도로 virtual 키워드를 붙이지 않아도 모두 가상함수로 취급됩니다.
그러나 virtual 키워드를 명시적으로 붙여주는게 가상함수임을 나타내기에 편리합니다.
#include <iostream>
class Person
{
public:
void Method()
{
std::cout << "Person's Method" << std::endl;
}
virtual void VirtualMethod()
{
std::cout << "Person's Virtual Method" << std::endl;
}
};
class Student : public Person
{
public:
void Method()
{
std::cout << "Student's Method" << std::endl;
}
virtual void VirtualMethod()
{
std::cout << "Student's Virtual Method" << std::endl;
}
};
class UnivStudent : public Student
{
public:
void Method()
{
std::cout << "UnivStudent's Method" << std::endl;
}
virtual void VirtualMethod()
{
std::cout << "UnivStudent's Virtual Method" << std::endl;
}
};
int main(int argc, char** argv) {
Person* person = new Person;
Student* student = new Student;
UnivStudent* univStudent = new UnivStudent;
//////////////////////////////////////////
person->Method();
student->Method();
univStudent->Method();
std::cout << std::endl;
((Person*)person)->Method();
((Person*)student)->Method();
((Person*)univStudent)->Method();
std::cout << std::endl;
//////////////////////////////////////////
person->VirtualMethod();
student->VirtualMethod();
univStudent->VirtualMethod();
std::cout << std::endl;
((Person*)person)->VirtualMethod();
((Person*)student)->VirtualMethod();
((Person*)univStudent)->VirtualMethod();
std::cout << std::endl;
//////////////////////////////////////////
std::cout << sizeof(Person) << std::endl;
std::cout << sizeof(Student) << std::endl;
std::cout << sizeof(UnivStudent) << std::endl;
std::cout << std::endl;
delete person;
delete student;
delete univStudent;
}
Person's Method
Student's Method
UnivStudent's Method
Person's Method
Person's Method
Person's Method
Person's Virtual Method
Student's Virtual Method
UnivStudent's Virtual Method
Person's Virtual Method
Student's Virtual Method
UnivStudent's Virtual Method
4
4
4
파생 관계에 있는 각 클래스에 가상 함수와 일반 함수를 준비하고 호출한 예제입니다.
포인터의 캐스팅을 하고 호출했을 때,
일반 함수는 '포인터'의 자료형을 따라 함수를 호출한 반면에
가상 함수는 '실제 인스턴스'의 자료형을 따라 함수를 호출했습니다.
또한, sizeof로 클래스의 크기를 측정했을 때 4라는 값이 측정되었는데
이는 가상 함수에 대한 정보를 컴파일러가 인스턴스에 포함시켰기 때문입니다.
- 멤버 변수가 아무것도 없는 클래스는 sizeof를 사용했을 때 보통 1byte가 출력됩니다.
가상 함수의 활용 방법 및 순수 가상함수에 대해서는 다른 장에서 이어서 다룹니다.