순수 가상 함수, 추상 클래스
이전에 순수 가상 함수를 사용하여 코드를 작성 한도 있고, 얼마 전에도 순수 가상 함수와 추상 클래스를 사용해 인터페이스를 정리했었지만, 당시에 제대로 이해를 하지 못 한 것 같아 정리를 하며 되짚어 보는것이 좋을 것 같다고 생각했다.
마침 오늘 강의에서 배운 내용을 바탕으로 순수 가상 함수와 추상 클래스에 대해 정리를 해 보았다.
순수 가상 함수란
- 순수 가상 함수는 선언만 존재하고 구현부는 없는 함수를 말한다.
- 따라서 순수 가상 함수를 가지는 클래스의 상속 클래스는 부모 클래스에서 선언한 순수 가상 함수를 구현해야 한다.
- 순수 가상 함수를 가지는 클래스는 추상 클래스가 되며, 인스턴스를 생성할 수 없다.
- 기본 인터페이스 정의
상속 클래스에서 구현해야 할 공통 기능을 선언한다.
- 다형성 구현
부모 클래스 포인터를 사용해 다양한 상속 클래스의 객체를 동일한 방식으로 구현할 수 있다.
- 재정의 강제
순수 가상 함수로 선언된 함수는 반드시 상속 클래스에서 구현되어야 하므로 설계에 강제성이 생긴다.
- 객체의 생성이 불가능하다.
- 포인터 혹은 참조로만 사용이 가능하다
순수 가상 함수의 선언

순수 가상 함수는 위와 같이
virtual '함수의 반환형' '함수 이름'() = 0;
과 같은 형식으로 선언을 할 수 있다.
virtual이란
'virtual'은 다형성을 구현하기 위해서 사용되는 키워드이다.
해당 키워드는 함수를 가상 함수로 선언하며 상속 클래스에서 override하여 재정의를 할 수 있게 된다.
이전에 했었던 동물 울음소리를 출력하는 코드를 예로 들어보면

위 코드와 같이 동일한 Walk 함수를 호출해도 출력 값이 각각 다르게 나오게 된다.
이는 IAnimal 클래스에서 Walk 함수의 선언만 하고, 정의는 각각 Dog 클래스와 Cat 클래스에서 했기 때문이다.
그렇다면 virtual 키워드를 사용하지 않으면 어떻게 될까
- 순수 가상 함수로 동작하지 않는다.
상속 클래스에서 재정의가 강제되지 않으며, 다형성도 제대로 동작하지 않게 된다.
- 추상 클래스가 되지 않는다.
순수 가상 함수가 아니게 되므로 해당 클래스가 추상 클래스가 되지 않고 객체를 직접 생성할 수 있게 된다.
그렇다면 추상 클래스란
추상 클래스란 순수 가상 함수를 포함하는 클래스를 말한다.
직접 객체를 생성할 수 없으며, 상속받은 상속 클래스가 순수 가상 함수를 구현한 경우에만 실행이 될 수 있다.
- 기본 인터페이스 정의
추상 클래스는 상속 클래스에 반드시 구현해야 하는 함수들을 선언하며 이를 통해 모든 상속 클래스에서 일관된 인터페이스를 구현할 수 있다.
- 코드의 재사용 용이
공통 기능을 추상 클래스에 작성함으로써 여러 상속 클래스에서 재사용이 가능하며 상속 클래스에 추가적으로 필요한 기능들은 각각의 클래스에서 추가하면 된다.
- 다형성 구현
추상 클래스를 기반으로 상속 클래스의 공통된 동작을 제공하거나 override를 통해 특화된 동작을 구현할 수 있다.
- 추상 클래스는 순수 가상 함수를 반드시 포함해야 한다.
- 추상 클래스를 상속받은 상속 클래스는 선언된 모든 순수 가상 함수를 정의해야 한다. (정의하지 않으면 추상 클래스가 됨)
- 추상 클래스에는 가상 소멸자를 선언해야한다. (new와 delete 키워드 사용)
인터페이스란
인터페이스는 특정 동작이나 기능을 상속 클래스에서 반드시 구현하도록 강제하는 설계이다.
보통 순수 가상 함수만 포함된 추상 클래스를 사용하기 때문에 추상 클래스와 기능이 비슷하다.
- 순수 가상 함수만 포함.
인터페이스는 구현된 메서드나 데이터 멤버를 포함하지 않고 모든 함수를 순수 가상 함수로 선언한다.
- 다중 상속 지원
여러 클래스를 상속하거나 상속받을 수 있으며, 원활하게 다양한 기능을 결합할 수 있다.
- 가상 소멸자 사용
인터페이스는 가상 소멸자를 포함하여 상속 클래스 객체를 안전하게 삭제할 수 있게 한다.
- 구현 강제
인터페이스를 상속받은 클래스는 모든 순수 가상 함수를 구현해야한다. (구현하지 않으면 추상 클래스가 됨)
- 표준화
개발자들이 반드시 구현해야할 동작들과 메서드를 정의한다.
Ex) Animal클래스를 상속받은 클래스들은 반드시 MakeSound()와 Walk() 메서드를 구현해야 한다.
- 다형성 구현
인터페이스를 통해 상속 클래스 객체를 인터페이스 타입의 포인터나 참조로 다룰 수 있게되고, 다양한 객체를 동일한 방식으로 처리할 수 있게 된다.
- 다중 상속 문제 해결
인터페이스는 구현이 되어있지 않으므로 다중 상속 시 충돌 문제가 발생할 확률이 매우 적다.
Ex) Eagle 클래스는 Animal 클래스와 Bird 클래스를 모두 상속 받을 수 있다.
추상 클래스와 인터페이스의 차이
| 특징 | 추상 클래스 | 인터페이스 |
|---|
| 목적 | 공통된 동작의 일부를 구현하거나 확장 가능. | 특정 동작을 반드시 구현하도록 강제. |
| 구현 가능 여부 | 일반 함수와 데이터를 포함 가능. | 구현 불가능(순수 가상 함수만 포함). |
| 다중 상속 | 다중 상속 시 충돌 위험이 있음(구현 포함 가능). | 다중 상속에 적합하며 충돌 없음. |
| 사용 방식 | 일부 공통 기능 제공 및 상속. | 표준화된 동작을 정의하고 강제. |
마치며
당장 이번 주 화요일에 진행한 강의만 하더라도 마지막에 인터페이스 예문을 구현하는데 오류가 발생을 했었는데, 아예 처음부터 다시 공부한다는 생각을 가지고 정리를 하니 확실이 이해가 더 된 느낌이 든다. 특히 virtual 키워드와 추상 클래스, 인터페이스의 정의를 정확하게 이해할 수 있었던 것 같다.