C++ 초급 - 8. 객체지향 프로그래밍 (3 - 순수 가상 함수 (= 0))
2025. 2. 22. 15:40ㆍ프로그래밍 언어/C++
📌 8.3 순수 가상 함수 (= 0)
C++에서 순수 가상 함수(Pure Virtual Function)는 자식 클래스에서 반드시 구현해야 하는 가상 함수를 의미한다.
이를 포함하는 클래스를 추상 클래스(Abstract Class)라고 하며, 추상 클래스는 직접 인스턴스를 생성할 수 없고, 인터페이스 역할을 한다.
📌 1. 순수 가상 함수란? (virtual 함수명() = 0;)
🔹 (1) 순수 가상 함수 정의
- 순수 가상 함수(Pure Virtual Function)는 = 0을 사용하여 선언하는 함수.
- 구현 없이 선언만 존재하며,
해당 클래스를 상속받은 자식 클래스에서 반드시 오버라이딩해야 함.
💡 기본 문법
class 클래스이름 {
public:
virtual void 함수명() = 0; // 순수 가상 함수 선언
};
💡 예제: 순수 가상 함수 선언
class Animal {
public:
virtual void makeSound() = 0; // 순수 가상 함수 (추상 클래스)
};
- makeSound()는 구현 없이 선언만 되어 있으며, = 0을 사용하여 순수 가상 함수로 정의됨.
- 이를 상속받는 자식 클래스에서 반드시 오버라이딩하여 구현해야 함.
📌 2. 추상 클래스(Abstract Class)의 역할
🔹 (1) 추상 클래스란?
- 순수 가상 함수를 하나 이상 포함하는 클래스를 추상 클래스(Abstract Class)라고 함.
- 추상 클래스는 직접 객체(인스턴스) 생성이 불가능하며, 반드시 상속을 통해 기능을 확장하여 사용해야 함.
- 인터페이스(Interface) 역할을 수행하며, 자식 클래스가 특정 기능을 구현하도록 강제함.
💡 예제: 추상 클래스 사용
#include <iostream>
// 추상 클래스 (순수 가상 함수 포함)
class Animal {
public:
virtual void makeSound() = 0; // 순수 가상 함수 (자식 클래스에서 반드시 구현해야 함)
};
// 구체적인 클래스 (추상 클래스를 상속받아 구현)
class Dog : public Animal {
public:
void makeSound() override { std::cout << "멍멍!" << std::endl; }
};
class Cat : public Animal {
public:
void makeSound() override { std::cout << "야옹!" << std::endl; }
};
int main() {
// Animal a; // ❌ 오류! (추상 클래스는 직접 인스턴스 생성 불가)
Animal* dog = new Dog();
Animal* cat = new Cat();
dog->makeSound(); // ✅ "멍멍!"
cat->makeSound(); // ✅ "야옹!"
delete dog;
delete cat;
return 0;
}
🔹 출력 결과
멍멍!
야옹!
💡 설명
- Animal 클래스는 makeSound()를 순수 가상 함수로 선언 → 추상 클래스가 됨.
- Dog와 Cat 클래스는 makeSound()를 반드시 오버라이딩하여 구현.
- Animal* dog = new Dog(); → 부모 클래스 포인터를 사용하여 다형성 활용 가능.
- Animal a; → 컴파일 에러 발생 (추상 클래스의 인스턴스 생성 불가).
📌 3. 순수 가상 함수의 구현 방식
🔹 (1) 자식 클래스에서 반드시 override하여 구현해야 함
- 순수 가상 함수가 선언된 부모 클래스를 상속받는 경우, 자식 클래스에서 반드시 오버라이딩해야 함.
- 자식 클래스가 해당 함수를 오버라이딩하지 않으면, 자식 클래스도 추상 클래스가 됨.
💡 예제: 순수 가상 함수를 오버라이딩하지 않은 경우
class Bird : public Animal {
// makeSound()를 오버라이딩하지 않으면 Bird도 추상 클래스가 되어 객체 생성 불가
};
🔹 결과
컴파일 오류 발생! (Bird 클래스도 추상 클래스가 됨)
💡 올바른 방법
class Bird : public Animal {
public:
void makeSound() override { std::cout << "짹짹!" << std::endl; }
};
📌 4. 가상 함수 테이블(Virtual Table, V-Table)과 다형성 원리
🔹 (1) 가상 함수 테이블(V-Table)이란?
- C++에서 가상 함수를 사용하는 경우, 객체는 가상 함수 테이블(Virtual Table, V-Table)을 가짐.
- V-Table은 클래스의 가상 함수 포인터를 저장하는 테이블로, 객체가 호출해야 할 가상 함수를 런타임에 동적으로 결정한다.
🔹 (2) V-Table을 활용한 다형성 원리
- 일반 함수 호출: 컴파일 타임(정적 바인딩)에서 결정됨.
- 가상 함수 호출: V-Table을 통해 런타임(동적 바인딩)에서 결정됨.
💡 예제: 가상 함수 테이블을 활용한 다형성
#include <iostream>
class Base {
public:
virtual void show() { std::cout << "Base 클래스" << std::endl; }
};
class Derived : public Base {
public:
void show() override { std::cout << "Derived 클래스" << std::endl; }
};
int main() {
Base* ptr = new Derived(); // 부모 클래스 포인터로 자식 객체 생성
ptr->show(); // ✅ Derived 클래스의 함수가 호출됨 (V-Table을 통한 동적 바인딩)
delete ptr;
return 0;
}
🔹 출력 결과
Derived 클래스
💡 설명
- 컴파일 타임에는 Base의 show()가 호출될 것처럼 보이지만,
V-Table을 활용하여 런타임에 Derived의 show()가 실행됨 (동적 바인딩 적용).
📌 5. 정리
개념 | 설명 |
순수 가상 함수 | virtual 함수명() = 0; 형태로 선언되며, 자식 클래스에서 반드시 구현해야 함 |
추상 클래스 | 순수 가상 함수를 하나 이상 포함하는 클래스 (인스턴스 생성 불가) |
인터페이스 역할 | 추상 클래스는 인터페이스 역할을 수행하며, 특정 기능을 자식 클래스에서 강제 구현하도록 함 |
오버라이딩 필수 | 순수 가상 함수를 오버라이딩하지 않으면 자식 클래스도 추상 클래스가 됨 |
가상 함수 테이블(V-Table) | 런타임에 동적으로 함수를 결정하는 테이블, 다형성의 핵심 원리 |
'프로그래밍 언어 > C++' 카테고리의 다른 글
C++ 초급 - 8. 객체지향 프로그래밍 (5 - C++11의 override와 final) (0) | 2025.02.22 |
---|---|
C++ 초급 - 8. 객체지향 프로그래밍 (4 - 인터페이스 개념 (Interface)) (0) | 2025.02.22 |
C++ 초급 - 8. 객체지향 프로그래밍 (2 - virtual 함수와 오버라이딩 (Overriding)) (0) | 2025.02.22 |
C++ 초급 - 8. 객체지향 프로그래밍 (1 - 캡슐화(Encapsulation), 상속(Inheritance), 다형성(Polymorphism)) (0) | 2025.02.22 |
C++ 초급 - 7. 구조체와 클래스 (6 - const 멤버 함수) (0) | 2025.02.22 |