하지만 실제 호출되는 코드는 Staff( ) 클래스의 PayChck( ) 멤버함수이다.
왜 그렇게 될까?
만약 위 코드가 자바(Java)라면 예상대로 오버라이딩 된 Permanent 클래스의 함수가 호출되었을 것이다.
하지만 c++에서는 위 코드만으로는 오버라이딩이 발생하지 않으며, 기본적으로 객체가 멤버 함수를 호출할 때 타입을 보고 타입에 해당되는 멤버 함수를 호출하기 때문이다.
따라서, 위 코드에서 Permanent의 PayCheck 멤버함수가 호출되기 위해서는 가상 함수(virtual Function)가 필요하다.
사용법은 타입 클래스의 멤버 함수 앞에 "virtual"을 붙여주면 된다.
class Staff {
public:
virtual double PayCheck() const {
return 0.0;
}
이와 같이 타입으로 명시된 클래스의 멤버 함수 앞에 "virtual"을 붙여 가상 함수화 시켜주면
Staff* emp = (Staff*)&rgl;
emp->PayCheck();
코드가 호출될 때, 원래라면 호출되어야 하는 Staff의 PayCheck가 가상함수화되었기 때문에 실제로 존재하는 Permanent의 PayCheck를 호출하게 되는 것이다.
즉, 가상함수란
- 자식 클래스에서 오버라이딩 될 것으로 예상되는 멤버함수를 의미
- 상속 관계에서 부모 클래스와 자식 클래스 모두에게 같은 이름의 멤버함수가 존재하되, 자식 클래스의 멤버함수를 재정의 가능
- 상속성의 문제점은 부모 클래스의 객체를 통해 자식 클래스에서 오버라이딩 된 함수를 호출할 수 없기에 이러한 문제점을 해결하기 위한 함수
이다.
그럼 가상화된 부모의 함수는 사라진것일까?
미리 답을 하자면, 부모의 함수도 사용을 할 수 있다.
void main( ) {
Staff emp2("kim", "suwon", 300);
Staff* emp = (Staff*)&emp2;
emp->PayCheck();
}
위 코드와 같이 Staff 타입 자기 자신으로 객체를 생성해서 호출하면 당연히 Staff의 PayCheck( ) 멤버함수가 호출된다.
정리하면, 부모 클래스의 함수를 가상화하여 자식 객체가 물려받았을 때 부모는 호출되는 우선순위가 밀려나는 것으로, 없어지진 않는다.
가상함수는 그럼 어떤점이 좋아서 사용하는것일까?