Replicated

[C++] virtual 탐구 본문

지식

[C++] virtual 탐구

라구넹 2025. 5. 27. 14:10
class Base {
public:
    void sayHello() { std::cout << "Hello from Base\n"; }
    virtual void greet() { std::cout << "Greet from Base\n"; }
};

class Derived : public Base {
public:
    void sayHello() { std::cout << "Hello from Derived\n"; }
    void greet() override { std::cout << "Greet from Derived\n"; }
};

int main() {
    Base* ptr = new Derived;
    ptr->sayHello();  // Base::sayHello()
    ptr->greet();     // Derived::greet()  ← virtual 덕분에 동적 바인딩
}

sayHello -> 정적 바인딩 => 컴파일 타임에 결정

greet -> 런타임에 동적으로 호출

 

 

가상 함수 테이블 (vtable)

- 클래스에 하나라도 virtual 있음 => vtable 생성

- 객체는 해당 클래스의 vptr(가상 테이블 포인터) 소유

- 가상 함수 호출: vptr을 따라간 뒤 vtable에서 함수 포인터를 통해 호출

* 추가적인 포인터 참조이기에 성능 오버헤드는 있음

 

 

override와 final

override: 안써도 작동은 하는데, 오타 방지 등을 위해 권장 사항

final: 더 이상 오버라이드 불가

 

소멸자와 virtual

기본 클래스의 소멸자는 반드시 virtual로 선언해야 함

이렇게 안하면 파생 클래스의 소멸자가 호출되지 않아 리소스 누수 발생 위험

 

순수 가상 함수와 추상 클래스

class Abstract {
public:
    virtual void run() = 0;  // 순수 가상 함수
};

인스턴스화 불가, 반드시 파생 클래스에서 구현 필요

 

 

virtual vs non-virtual

항목 virtual non-virtual
바인딩 시점 런타임 컴파일 타임
오버헤드 vtable 참조 없음
인라인화 어려움 가능
유연성 높음 낮음

 

 

다중 상속에서의 가상 함수

class A {
public:
    virtual void f();
};

class B {
public:
    virtual void g();
};

class C : public A, public B {
public:
    void f() override;
    void g() override;
};

C -> 두 개의 vptr,, 각각 A, B의 vtable을 관리

 

virtual 런타임 다형성을 구현하는 키워드
override 오버라이딩 의도를 명확히 함
final 더 이상 오버라이딩 금지
vtable 클래스별 가상 함수 목록
vptr 객체가 vtable을 가리키는 포인터
가상 소멸자 상속 구조에서 필수
성능 약간의 오버헤드 존재

 

'지식' 카테고리의 다른 글

[Math] 내적  (0) 2025.05.28
[C++] 상속 시 생성자 탐구  (0) 2025.05.27
[C++] L Value & R Value  (0) 2025.05.27
[DS] C++ Deque 랜덤 액세스 O(1)?  (0) 2025.03.21
[OS] 스레드 세이프  (0) 2025.03.21