순수 가상 함수(Pure Virtual Function)
가상 함수 중 파생 클래스에서 반드시 재정의해야 하는 멤버 함수
- 함수의 동작을 정의하는 본체를 가지고 있지 않다.
- 파생 클래스에서 재정의하지 않으면 사용할 수 없다.
순수 가상 함수 선언
- 순수 가상 함수를 선언하는 문법은 다음과 같다.
virtual 멤버함수의원형=0; // '=0'은 함수만 있고 본체는 없다는 의미
순수 가상 함수 예제
#include <iostream> using namespace std; class Animal { public: Animal() {} virtual ~Animal() {} // 가상 소멸자 선언 virtual void Cry() = 0; // 순수 가상 함수 선언 }; class Dog : public Animal { public: Dog() : Animal() {} virtual void Cry() { cout << "Woof Woof!!" << endl; } }; class Cat : public Animal { public: Cat() : Animal() {} void Cry() override { cout << "Meow Meow~~" << endl; } }; int main(void) { Dog dog; Cat cat; dog.Cry(); cat.Cry(); return 0; }
Woof Woof!! Meow Meow~~
- 유의할 점으로 순수 가상 함수를 멤버로 갖는 Animal은 함수를 호출하는 것은 물론, 객체를 생성하는 것조차 불가능하다. (컴파일 오류 발생)
- 이는 C++에서 순수 가상 함수를 1개 이상 포함하는 모든 클래스의 객체를 생성할 수 없도록 만들었기 때문이다. 순수 가상 함수를 1개 이상 포함하여 반드시 상속이 필요한 클래스를 추상 클래스(abstract class)라고 한다.
추상 클래스(Abstract Class)
하나 이상의 순수 가상 함수를 포함하는 클래스
- 추상 클래스를 상속받는 모든 파생 클래스들은 순수 가상 함수를 반드시 재정의해야 한다.
- 추상 클래스 자체로 인스턴스화할 수 없다. 반드시 파생클래스로의 상속이 필요한 일종의 '설계도'이다.
- 추상 클래스는 다음의 용도로는 사용할 수 없다.
- 변수 또는 멤버 변수
- 함수의 전달되는 인수 타입
- 함수의 반환 타입
- 명시적 타입 변환의 타입
class Animal { public: Animal() {} virtual ~Animal() {} // 가상 소멸자 선언 virtual void Cry() = 0; // 순수 가상 함수 선언 };
- 위 예제에서는 Animal이 추상 클래스이다.
추상 클래스를 가리키는 포인터
- 추상 클래스 자체의 객체를 생성할 수는 없지만, 추상 클래스를 가리키는 포인터는 만들 수 있다.
- 앞선 예제의 main에서 아래와 같이 Animal 포인터를 만들어 오버라이딩을 수행할 수 있다.
int main(void) { Animal* dog = new Dog(); Animal* cat = new Cat(); dog->Cry(); cat->Cry(); return 0; }
// 결과 Woof Woof!! Meow Meow~~