가상함수 (virtual function 또는 virtual method) :
-상속하는 클래스 내에서 같은 시그니처의 함수로 오버라이딩 될 수 있는 함수 또는 메소드 이다.
-파생 클래스에서 재정의할 것으로 기대하는 멤버함수를 의미한다. 이러한 가상 함수는 자신을 호출하는 객체의 동적 타입에 따라 실제 호출할 함수가 결정된다.
-기본 클래스(상속되지 않은 클래스) 내에서 선언되어 파생 클래스에 의해 재정의되는 멤버함수입니다.
문법 )
c++에서 가상함수는 virtual 키워드를 사용하여 선언한다.
virtual 멤버함수의원형
(파생 클래스의 멤버 함수 쪽에도 virtual키워드를 사용하여 가상함수라는 것을 명확히 하는 것도 나쁘지 않습니다.)
동적바인딩 (dynamic binding)
c++컴파일러는 함수를 호출할 때, 어느 블록에 있는 함수를 호출해야 하고, 해당 함수가 저장된 정확한 메모리 위치까지도 알아야한다.
이처럼 함수를 호출하는 코드에서 어느 블록에 있는 함수를 실행하라는 의미로 해석하는 것을 바인딩(binding)이라고 한다.
가상함수의 호출은 컴파일러가 어떤 함수를 호출해야 하는지 미리 알 수가 없습니다.
왜냐하면, 가상함수는 프로그램이 실행될 때 객체를 결정하므로, 컴파일 타임에 해당 객체를 특정할 수 없기 때문.
따라서 가상함수의 경우에는 런타임에 올바른 함수가 실행될 수 있도록 해야한다.
이것을 동적 바인딩 또는 지연 바인딩이라고 한다.
순수 가상 함수 (pure virtual function) :
C++에서 가상 함수(virtual function)는 파생 클래스에서 재정의할 것으로 기대하는 멤버함수를 의미한다.
따라서 가상함수는 반드시 재정의해야만 하는 함수가 아닌, 재정의가 가능한 함수를 가리킨다.
이와는 달리 순수 가상 함수(pure virtual function)이란 파생클래스에서 반드시 재정의해야하는 멤버함수를 의미한다.
이러한 순수 가상 함수는 일반적으로 함수의 동작을 정의한느 본체를 가지고 있지 않다.
따라서 파생클래스(상속받은 클래스)에서 재정의하지 않으면 사용할 수 없다.
문법 )
virtual 멤버함수의원형 =0;
// 일반 virtual function과의 차이점은 끝에 "=0"을 추가한다는 것.
추상 클래스 (abstract class) :
하나 이상의 순수 가상 함수를 포함하는 클래스를 추상 클래스라고 한다.
이러한 추상 클래스는 oop에서 다형성을 가진 함수의 집합을 정의할 수 있게 해준다.
즉, 반드시 사용되어야 하는 멤버 함수를 추상 클래스에 순수 가상 함수로 선언해 놓으면, 이 클래스로부터 파생된 모든 클래스에서는 이 가상 함수를 반드시 재정의해야한다.
추상 클래슨느 동작이 정의되지 않은 순수 가상함수를 포함하고 있으므로, 인스턴스를 생성할 수 없다.
따라서 추상 클래스는 먼저 상속을 통해 파생 클래스를 만들고, 만든 파생클래스에서 순수 가상함수를 모두 오버라이딩하고 나서야 비로소 파생 클래스의 인스턴스를 생성할 수 있게 된다.
하지만 추상 클래스 타입의 포인터와 참조는 바로 사용할 수 있다.
예제
class Animal
{
public :
virtual ~Animal() {} // 가상 소멸자의 선언
virtual void Cry()=0; // 순수 가상 함수의 선언
};
// Animal클래스를 상속받은 Dog클래스
class Dog : public Animal
{
public :
virtual void Cry() { cout << "멍멍!" >> endl; }
// 가상함수를 재정의(overriding)
};
class Cat : public Animal
{
public :
virtual void Cry() { cout < < "야옹야옹!!" > > endl; }
};
int main(void)
{
Dog my_dog;
my_dog.Cry();
Cat my_cat;
my_cat.Cry();
return 0;
}
실행결과
멍멍!!
야옹야옹!!
위의 예제에서 추상 클래스인 Animal 클래스는 순수 가상 함수은 Cry() 멤버 함수를 가지고 있다.
Animal 클래스를 상속받는 파생 클래스인 Dog 클래스와 Cat클래스는 Cry() 함수를 오버라이딩해야만 인스턴스를 생성할 수 있다.
추상 클래스의 용도 제한
c++에서 추상 클래스는 다음과 같은 용도로 사용할 수 없다.
1. 변수 또는 멤버 변수
2. 함수의 전달되는 인수 타입
3. 함수의 반환타입
4. 명시적 타입 변환의 타입