본문 바로가기

C++ 기초 1

[C++] 5-2 가상 함수(Virtual function)

가상 함수

   부모 클래스 내에 정의되어 있는 멤버 함수를 가상 함수(virtual function)로 만들면 자식 클래스에서 재정의하여 사용할 수 있다. 부모 클래스의 멤버 함수를 가상 함수로 만들기 위해서는 예약어 virtual를 입력하면 된다. 

   부모 클래스의 가상 함수를 상속받은 자식 클래스에서는 그 가상 함수를 재정의하여 사용할 수 있다. 이때 예약어 virtual은 생략한다. 가상 함수의 재정의는 함수 오버로드(overloading)와 비슷해 보이지만 전혀 다른 개념이다. 함수의 오버로드는 매개변수의 개수와 데이터 형태가 달라야 한다. 하지만 가상 함수의 재정의해서는 매개변수의 개수와 데이터 형태 그리고 return값의 데이터 형태가 동일해야 하며, 가상 함수는 클래스의 멤버이어야 한다. 이처럼 가상함수를 재정의 하는 것을 오버라이드(overriding)라 한다. 

 

 
예제
#include <iostream>
using namespace std;
class parent {	//부모 클래스 정의
public:
	char* name;
	parent(char* n) {	//생성자
		name = n;
	}
	virtual void output() {	//가상 함수
		cout << "parent의 멤버 output(): ";
		cout << "name=" << name << endl;
	}
};

class child1 :public parent {	//첫번째 자식 클래스 정의
public:
	int age;
	child1(char* n, int a): parent(n) {	//생성자
		age = a;
	}
	void output() {
		cout << "child1의 멤버 output(): ";
		cout << name << " " << age << endl;
	}
};

class child2 :public parent {	//두번째 자식 클래스 정의
public:
	int height;
	child2(char* n, int h) : parent(n) {	//생성자
		height = h;
	}
};

int main()
{
	parent* p;	//부모 클래스의 포인터
	parent ob((char*) "Hong");	//부모 클래스의 객체
	child1 ob_c1((char*)"Hong", 6);	//첫번째 자식 클래스의 객체
	child2 ob_c2((char*)"Hong", 120);	//두번째 자식 클래스의 객체
	p = &ob;	//부모 클래스의 객체를 가리킴
	p->output();	//parent의 output()를 참조
	p = &ob_c1;	//첫번째 자식 객체 ob_c1를 가리킴
	p->output();	//child1의 output()를 참조
	p = &ob_c2;	//두번째 자식 객체 ob_c1를 가리킴
	p->output();	//parent의 output()를 참조
	return 0;
}
실행 결과
parent의 멤버 output(): name=Hong
child1의 멤버 output(): Hong 6
parent의 멤버 output(): name=Hong
  • 부모 클래스에서 멤버 함수 output()를 가상 함수로 정의했다.
  • 자식 클래스 child1에서는 output()를 오버라이드했다.
  • 자식 클래스 child2에서는 output()를 오버라이드하지 않았다. 
  • 부모 클래스 포인터 p에 ob_c2의 주소를 대입하고 p를 통해 output()를 호출하면 부모 클래스의 output()가 호출되어 실행된다. 

 

참고

1. 장인성 외 5인, (초보자도 쉽게 따라 할 수 있는) C++프로그래밍, 광문각, 2017.02.13