C++ 에서는 "부모 클래스로 자식 객체를 관리" 하는 다형성이라는 개념이 있습니다.
이 개념을 확장하면 순수 가상 함수, 추상 클래스, 인터페이스라는 용어들이 등장하는데 이 글에서는 이와 관련된 내용을 정리해 보겠습니다.
1. 순수 가상 함수 (Pure Virtual Function)
순수 가상 함수는 함수를 선언만 하고 본체 (구현부) 를 작성하지 않는 함수입니다.
문법적으로는 함수 선언 뒤에 = 0; 을 붙여 표현합니다.
함수를 순수 가상 함수로 선언하면, 부모는 자식 클래스에게 "이런 기능이 반드시 있어야 해" 라고 지시하는 입장인 것이고, 실제 동작은 상속받는 자식이 정의하도록 강제합니다.
class Animal {
public:
// 순수 가상 함수: 본체가 없고 = 0이 붙음
virtual void speak() = 0;
virtual ~Animal() {} // 다형성을 위한 가상 소멸자는 필수!
};
2. 추상 클래스 (Abstract Class)
클래스 내부에 순수 가상 함수가 하나라도 포함되어 있다면, 그 클래스는 자동으로 추상 클래스가 됩니다.
설계도가 미완성 상태이므로 new Animal() 처럼 객체를 직접 생성 (인스턴스화) 할 수 없습니다.
추상 클래스는 자식 클래스들의 공통적인 특징을 모아놓은 '기본 틀' 역할을 합니다.
3. 인터페이스 (Interface)
C++ 에는 interface 라는 별도의 키워드가 없습니다.
대신, 모든 함수가 순수 가상 함수로만 이루어진 클래스를 인터페이스라고 부릅니다.
참고로 C# 에는 interface 라는 keyword 가 별도로 존재합니다.
인터페이스는 멤버 변수나 구현된 함수가 전혀 없습니다. 오직 "무엇을 해야 하는지"에 대한 목록만 존재합니다.
서로 다른 클래스들이 동일한 방식으로 동작하도록 '표준 규격' 을 정해주고, 구현은 상속을 받은 자식 클래스에서 각 클래스의 성격에 맞게 구현을 하는 방식입니다.
// C++ 스타일 인터페이스
class IRemoteControl {
public:
virtual void turnOn() = 0;
virtual void turnOff() = 0;
virtual ~IRemoteControl() {}
};
4. 예시 코드
#include <iostream>
#include <vector>
#include <memory>
// 1. 추상 클래스 (인터페이스 역할)
class Animal {
public:
virtual void speak() = 0; // 순수 가상 함수
virtual ~Animal() {} // 가상 소멸자
};
// 2. 자식 클래스: 반드시 순수 가상 함수를 구현해야 함
class Dog : public Animal {
public:
void speak() override { std::cout << "멍멍!" << std::endl; }
};
class Cat : public Animal {
public:
void speak() override { std::cout << "야옹~" << std::endl; }
};
int main() {
// Animal a; // 에러! 추상 클래스는 객체를 만들 수 없음
// 부모 포인터로 자식 객체들을 관리 (다형성)
std::vector<std::unique_ptr<Animal>> zoo;
zoo.push_back(std::make_unique<Dog>());
zoo.push_back(std::make_unique<Cat>());
for (const auto& animal : zoo) {
animal->speak(); // 각자 오버라이딩된 함수가 호출됨
}
return 0;
}
5. 정리
| 용어 | 정의 | 객체 생성 가능 여부 | 핵심 포인트 |
| 순수 가상 함수 | 구현 없이 = 0으로 선언된 함수 | - | 자식에게 구현을 강제함 |
| 추상 클래스 | 순수 가상 함수를 1개 이상 가진 클래스 | X | 상속을 위한 미완성 설계도 |
| 인터페이스 | 모든 함수가 순수 가상 함수인 클래스 | X | 클래스 간의 소통 규격(약속) |
C++ 에서 추상 클래스는 프로그램을 유연하고 확장이 용이한 구조로 만드는데 중요한 역할을 합니다.
'C++' 카테고리의 다른 글
| [C++] Enum 의 진화와 실무적인 절충안 (0) | 2026.02.26 |
|---|---|
| [C++] static 완전히 이해하기 (0) | 2026.02.25 |
| [C++] 헤더 파일에서 Namespace와 const를 사용해 설정값 관리하기 (0) | 2026.02.18 |
| [C++] 값 복사는 무조건 느리다는 편견과 현대적 기준 (0) | 2026.02.15 |
| 참조 반환(Return by Reference)의 이해와 활용 (0) | 2026.01.27 |