C++
[C++] 가상 함수 (virtual function)
코딩 메모장
2025. 4. 23. 23:13
728x90
[C++] 가상 함수 (virtual function
)
가상 함수는 C++에서 다형성(polymorphism)을 구현하기 위한 핵심 개념입니다. 주로 상속 구조에서 기본 클래스 포인터(또는 참조)를 통해 파생 클래스의 함수를 호출할 수 있도록 도와줍니다.
1. 가상 함수란?
virtual
키워드를 사용하여 기본 클래스에 선언된 멤버 함수입니다.- 파생 클래스에서 재정의(overriding)할 수 있으며, 이를 통해 런타임 다형성(runtime polymorphism)이 가능합니다.
class Base {
public:
virtual void show(); // 가상 함수
};
2. 런타임 다형성의 동작 원리
가상 함수는 동적 바인딩(dynamic binding)을 지원합니다. 즉, 컴파일 시점이 아닌 실행 시간에 어떤 함수가 호출될지를 결정합니다.
✅ 가상 함수 예제
class Base {
public:
virtual void show() {
std::cout << "Base class show function.\n";
}
};
class Derived : public Base {
public:
void show() override {
std::cout << "Derived class show function.\n";
}
};
void display(Base* base) {
base->show(); // 런타임에 실제 객체 타입에 따라 호출
}
int main() {
Base b;
Derived d;
display(&b); // Base class show function.
display(&d); // Derived class show function.
}
3. 가상 함수가 아닐 때의 예제
class Base {
public:
void show() { // 가상 함수가 아님
std::cout << "Base class show function.\n";
}
};
class Derived : public Base {
public:
void show() {
std::cout << "Derived class show function.\n";
}
};
int main() {
Base* base = new Derived();
base->show(); // Base class show function. (정적 바인딩)
delete base;
}
✅ virtual
키워드가 없으면 컴파일 시점에 함수가 결정되며, 파생 클래스에서 오버라이딩해도 호출되지 않습니다.
4. 가상 소멸자
기본 클래스의 소멸자는 반드시 virtual
로 선언하는 것이 좋습니다. 그렇지 않으면 파생 클래스 객체를 기본 클래스 포인터로 삭제할 때 파생 클래스 소멸자가 호출되지 않아 메모리 누수가 발생할 수 있습니다.
class Base {
public:
virtual ~Base() { std::cout << "Base destructor\n"; }
};
class Derived : public Base {
public:
~Derived() { std::cout << "Derived destructor\n"; }
};
int main() {
Base* ptr = new Derived();
delete ptr; // Derived destructor → Base destructor (정상 호출)
}
5. 순수 가상 함수와 추상 클래스
순수 가상 함수는 함수 정의 없이 = 0
으로 선언합니다. 해당 함수가 하나라도 있으면 추상 클래스(abstract class)가 되며, 이 클래스는 인스턴스를 생성할 수 없습니다.
class Animal {
public:
virtual void speak() = 0; // 순수 가상 함수
};
class Dog : public Animal {
public:
void speak() override {
std::cout << "멍멍!\n";
}
};
✅ 인터페이스처럼 사용되며, 파생 클래스에서 반드시 구현해야 합니다.
✅ 요약
항목 | 설명 |
---|---|
virtual 함수 |
런타임에 함수 호출 결정 (동적 바인딩) |
오버라이딩 | 파생 클래스에서 재정의 가능 |
가상 소멸자 | 파생 클래스 소멸자 호출 보장 |
순수 가상 함수 | 추상 클래스 생성용, 반드시 오버라이딩 필요 |
성능 | 일반 함수보다 약간 느리지만 다형성을 위해 필수 |
728x90