가상 함수 테이블(vtable) 개념
가상함수는 실행시간에 어떻게 타입을 조사할까?
실행시간에 해당 함수 호출하려면 함수 주소를 알아야 한다.
C++ 컴파일러는 가상 함수 테이블(vtable) 을 생성하여
런타임에 올바른 함수를 찾는다.
** 가상함수 원리는 컴파일러 종류와 버전에 따라 다를 수 있다.
#include <iostream>
using namespace std;
class Base
{
int d;
public:
virtual void f1() {}
virtual void f2() {}
virtual void f3() {}
};
class Derived : public Base
{
int d;
public:
virtual void f2() override {}
};
int main()
{
Base b1, b2;
}
• 클래스에 하나 이상의 가상 함수가 있으면
• 컴파일러는 해당 클래스의 vtable 생성
• 각 클래스의 vtable에는 가상 함수들의 주소 저장
• 객체에는 vtable을 가리키는 포인터(vptr)가 숨겨진 멤버로 포함
#include <iostream>
using namespace std;
class Base
{
int d;
public:
virtual void f1() {}
virtual void f2() {}
virtual void f3() {}
};
class Derived : public Base
{
int d;
public:
virtual void f2() override {}
};
int main()
{
Derived d1;
Base* p = &d1;
p->f2(); // p->ptrtable[2]()
}
가상 함수를 호출할 때
vptr 통해 vtable에서 해당 함수의 주소 찾아 실행.
→ 가상함수가 선언된 순서를 가지고 검색
ex) "p->f2()" 는 2번째 선언된 가상함수로
테이블에서 2번째 항목을 주소로 꺼내 호출
• 가상 함수 호출 시 주소를 꺼내서 호출하므로 overhead 발생
→ 인라인 치환 될 수 없음
• 클래스마다 하나의 vtable이 생성되고
객체마다 vptr 포인터(보통 8바이트)가 추가기에
많은 객체를 생성할 경우 vptr 포인터가 차지하는 메모리가 누적될 수 있음
#include <iostream>
using namespace std;
class Base
{
int d;
public:
virtual void f1() {}
virtual void f2() {}
virtual void f3() {}
};
class Derived : public Base
{
int d;
public:
virtual void f2() override {}
};
int main()
{
Base b1, b2;
Derived d1;
Base* p = &d1;
p->f2(); // p->ptrtable[2]()
}
실제 객체 크기를 확인해보면
멤버변수 외 가상함수 포인터 포함하고 있는 것을 확인할 수 있다.
memory align 이나 컴파일러에 따라 결과 다를 수 있음
#include <iostream>
using namespace std;
class Base
{
int d;
public:
virtual void f1() {}
virtual void f2() {}
virtual void f3() {}
};
class Derived : public Base
{
int d;
public:
virtual void f2() override {}
};
int main()
{
Base b1;
Derived d1;
cout << sizeof(b1) << endl;
cout << sizeof(d1) << endl;
}
Base = "8B" + 8B
Derived = "8B" + 8B + 8B
[C++] 인라인(inline) 함수
키워드 「inline」 로 정의된 함수를 "인라인 함수"라 한다. 보통, 구조가 간단한 함수를 inline 처리해야 효율성을 높일 수 있다. inline void Add(int a, int b) { return a + b; } 클래스 또는 구조체 안에 멤버
zoosso.tistory.com
📌 [C++] 가상 함수 (virtual funciton)
[C++] 가상 함수 (virtual funciton)
가상 멤버 함수 (virtual function)동적 바인딩을 위해 사용class A{public: virtual void sub(void);}; [예제] 함수 재정의(overriding) 주의사항#include class Animal{public: void Cry() { std::cout Cry(); // ??? -> Dog? Animal?}Q) p-
zoosso.tistory.com
[C++] 가상 소멸자
가상 소멸자 C++에서는 가상 함수(virtual)가 하나라도 있는 클래스라면 소멸자도 virtual로 만드는 것이 안전한 습관이다. [예제] 부모-자식 객체 생성자/소멸자 순서 #include using namespace std;clas
zoosso.tistory.com
'프로그래밍 언어 > C++' 카테고리의 다른 글
[C++] ADL (Argument Dependent Lookup) (1) | 2025.03.09 |
---|---|
[C++] 대입 연산자 재정의 (Assignment Operator) (5) | 2025.03.07 |
[C++] 연산자 재정의 (Operator Overloading) (2) | 2025.03.05 |
[C++] 다중 상속 (multiple inheritance) (2) | 2025.03.04 |
[C++] dynamic_cast (1) | 2025.03.03 |
댓글