가상 함수란?
가상 함수(Virtual function)는 virtual 예약어를 붙여서 선언한 메서드이다. 가상 함수는 과거의 정의가 완전히 무시된다는 것이 특징이다.
사용 방법은 다음과 같다.
virtual 반환형식 메서드이름
함수앞에 virtual 예약어만 붙여주면 된다.
#include <iostream>
using namespace std;
//부모 클래스
class PClass
{
public:
//가상 함수
virtual void printNum()
{
cout << "PClass num : " << num << endl;
}
void TestFunc()
{
cout << "TestFunc()" << endl;
printNum();
}
protected:
int num = 10;
};
//파생 클래스
class CClass : public PClass
{
public:
//가상 함수 재정의
virtual void printNum()
{
cout << "CClass: " << num*2<< endl;
}
};
int main()
{
CClass a; //파생 클래스 객체생성
a.printNum();
PClass& b = a;
b.printNum();
a.TestFunc();
return 0;
}
결과값:
CClass: 20 //a.printNum()의 결과
CClass: 20 //b.printNum()의 결과
TestFunc() //a.TestFunc()의 결과
CClass: 20
virtual 예약어를 통해 기존의 부모 클래스에서 정의된 메소드가 완전히 오버라이드된 것을 확인할 수 있다. 가상 함수는 재정의된 메소드가 있다면 그 함수를 호출하는 것이다.
또한, 가상 함수는 일반 메소드와 달리 참조 형식과 관계없이 실 형식의 메소드를 호출한다. 만약, 부모 클래스에서 virtual 예약어를 지운다면 b.printNum(); 코드에 의해 'PClass : 10'이라는 결과가 나왔을 것이다. 일반 메소드는 참조 형식에 의해 어떤 메소드가 호출되는지 결정되기 때문이다.
마지막으로, TestFunc() 함수에서 printNum() 함수를 호출하는데 이 printNum()은 가장 마지막에 재정의된 함수를 호출한다.
부모 클래스에 대한 포인터나 참조자로 파생 클래스 인스턴스를 참조할 수 있다.
부모클래스 *a = new 파생클래스;
#include <iostream>
using namespace std;
//부모 클래스
class PClass
{
public:
PClass() { name = new char[10]; }
~PClass()
{
cout << "~PClass()" << endl;
delete name;
}
private:
char* name;
};
//파생 클래스
class CClass : public PClass
{
public:
CClass() { age = new int; }
~CClass()
{
cout << "~CClass()" << endl;
delete age;
}
private:
int* age;
};
int main()
{
PClass* a = new CClass;
delete a;
return 0;
}
결과값:
~PClass()
이 코드에는 문제점이 있다. 부모 클래스의 소멸자 호출은 이루어지나 파생 클래스의 소멸자는 호출되지 않는다. 즉, 참조 형식의 소멸자만 호출되고 실 형식의 소멸자는 호출되지 않는다.
소멸자를 가상화하여 해결할 수 있다.
virtual ~PClass()
{
cout << "~PClass()" << endl;
delete name;
}
결과값:
~CClass()
~PClass()
*상속 관계에서 가상 함수는 한 번 가상 함수면 영원히 가상 함수다. 즉 부모 클래스에서 가상 함수이면 파생 클래스에서 virtual 예약어를 사용하지 않더라도 자동으로 가상화된다.
'C++' 카테고리의 다른 글
[C++] 벡터(vector)와 메소드들(push_back, front, back, begin, end) (0) | 2019.12.28 |
---|---|
[C++] 순수 가상 클래스(Pure virtual class)와 순수 가상 함수 (0) | 2019.12.27 |
[C++] 메소드 오버라이드(Override) (0) | 2019.12.26 |
[C++] 생성자 상속 (0) | 2019.12.26 |
[C++] 접근 제어 지시자(public, protected, private) (0) | 2019.12.25 |