순수 가상 함수(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~~