C++에서 순수 가상 함수(Pure Virtual Function)란 함수의 구현부(정의)를 작성하지 않고 선언만 존재하는 가상 함수를 말합니다. 선언 시 = 0을 대입하는 방식으로 표시하며, 이는 해당 함수가 파생 클래스에서 반드시 재정의(오버라이딩)되어야 함을 컴파일러에게 알려주는 역할을 합니다.
추상 클래스(Abstract Class)는 이러한 순수 가상 함수를 하나 이상 포함하고 있는 클래스입니다. 추상 클래스는 객체 지향 프로그래밍에서 공통 인터페이스를 정의하는 설계도 역할을 수행합니다.
추상 클래스의 주요 특징
- 추상 클래스에는 순수 가상 함수뿐 아니라 일반 멤버 함수와 변수도 함께 포함될 수 있습니다.
- 추상 클래스는 직접 인스턴스화(객체 생성)할 수 없지만, 추상 클래스 타입의 포인터와 참조는 생성할 수 있습니다.
- 추상 클래스는 주로 업캐스팅(Upcasting)에 활용되어, 파생 클래스들이 기반 클래스의 인터페이스를 통해 다형성을 구현할 수 있게 합니다.
- 추상 클래스를 상속받은 파생 클래스는 모든 순수 가상 함수를 반드시 구현해야 합니다. 하나라도 구현하지 않으면 그 파생 클래스 역시 추상 클래스가 됩니다.
- Vtable(가상 함수 테이블)에 순수 가상 함수의 슬롯은 예약되지만 실제 함수 주소가 저장되지 않아 Vtable이 불완전한 상태로 남기 때문에, 추상 클래스의 객체는 생성할 수 없습니다.
예제 코드
#include<iostream>
using namespace std;
class B {
public:
virtual void s() = 0; // 순수 가상 함수
};
class D : public B {
public:
void s() {
cout << "Virtual Function in Derived class\n";
}
};
int main() {
B *b; // 추상 클래스 타입의 포인터는 생성 가능
D dobj; // 파생 클래스의 객체 생성
b = &dobj; // 업캐스팅
b->s(); // 다형성에 의해 파생 클래스의 함수 호출
}
실행 결과
Virtual Function in Derived class
위 예제에서 기반 클래스 B는 순수 가상 함수 s()를 가지므로 추상 클래스입니다. 따라서 B 타입의 객체는 만들 수 없지만, 포인터 b를 통해 파생 클래스 D의 객체를 참조하여 오버라이딩된 함수를 호출할 수 있습니다. 이것이 바로 추상 클래스가 제공하는 다형성의 핵심 원리입니다.