[C++] 가상 함수 테이블

2015. 4. 1. 03:32프로그래밍/C/C++

728x90
728x90

1. 서론

논란의 중심! 가상 함수 테이블!!!

말도 많고 탈도 많은 가상 함수 테이블..

아카데미에서 오버라이딩보다 더 심각한 뜨거움 감자가 된 가상 함수 테이블!


2. 토론

우리 조에선 이 가상 함수 테이블에 대한 이견이 그렇게 많지 않았다.

교수님이 말씀하신 1객체 1가상 함수 포인터 1가상 함수 테이블!

모두 수긍하는 부분이어서 더 이상 논의하지 않았다.

클래스의 함수들은 정적 바인딩이 되어 메모리상에 올라간다.


컴파일러에 의해 바인딩이 된 클래스는 서로 다른 가상 함수 테이블이 생긴다.(가상 함수가 있다면)

(하지만 이 방법과 구현된 형태는 모두 컴파일러가 관리하므로 정확하게 알 수 없다.)

여기서 가상 함수 테이블이 기존 부모의 테이블에서 '복사'한다는 개념때문에

수업 시간을 넘어가며 열띤 토론이 되었던 것이다.

인스턴스화 할때마다 이 복사가 일어난다고 생각하는 사람도 있었다.

다양한 생각이 있었지만 역시 교수님이 말씀하신 '승계'의 개념이 가장 옳다고 결론지었다.


여튼 이것은 이정도에서 일단락을 짓고.. 


가상함수 테이블에서 어떻게 오버라이딩이 일어나는가?

이것에 대해 조원들에게 조금 설명을 해보았다.


3. 실험

소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
 
class MyClass1
{
public:
    MyClass1(){ }
    ~MyClass1(){ }
    
    virtual void func1(){puts("부모"); }
    virtual void func2(){puts("부모"); }
    virtual void func3(){puts("부모"); }
 
private:
 
};
 
class MyClass2 : public MyClass1
{
public:
    MyClass2(){ }
    ~MyClass2(){ }
    
    void func1(){puts("asdf"); }
    void func2(){puts("zxcv"); }
    
private:
 
};
 
void main()
{
    MyClass1 temp;
    MyClass2 temp2;
    MyClass1* temp3 =new MyClass2;
    temp3->func1();
    temp3->func2();
    temp3->func3();
}
cs


결과


여기서 Base 클래스인 MyClass1이 포인터로 Derived 클래스인 MyClass2를 동적할당한 객체를 가리키게 한다.

결과에서 temp3이 Base 클래스 객체 포인터인데 __vfptr의 가상 함수 테이블 포인터가 있다.

fun3은 Derived 클래스에서 재정의하지 않았다.


1. temp3->func1();

temp3의 정적 타입은 MyClass1이다.(동적 타입은 MyClass2)

그렇기 때문에 ->func1()를 호출하면 MyClass1의 func1()을 찾게 된다.

하지만 func1이 가상 함수기때문에 temp3 객체는 가상 함수 테이블을 참조한다.

__vfptr의 0번 인덱스에 있는 void*는 MyClass2::func1(void)를 가리키고 있다.

그래서 Derived 클래스인 MyClass2의 func1이 호출되면서 "asdf"가 출력된다.

temp3->func2(); 도 같다.


2. temp3->func3();

func3도 가상 함수기떄문에 가상 함수 테이블을 보게 된다.

하지만 Derived 클래스에서 재정의 되지 않았으므로 자신의 함수를 그대로 참조하고 있다.

가상 함수 테이블의 2번 인덱스를 보면 MyClass1::func3(void)와 같이 됨을 알 수 있고.

결과 값도 Base 클래스의 func3이 호출되어 "부모"가 호출 된 것을 확인할 수 있다.

728x90
반응형

'프로그래밍 > C/C++' 카테고리의 다른 글

[STL] vector의 at()과 []의 차이  (1) 2015.07.11
2차원 벡터 사용하기  (1) 2015.07.08
비트 연산으로 정수에서 이진수 0,1 뽑아내기  (0) 2015.07.08
RTTI , 캐스팅  (0) 2015.03.31
오버라이딩(Overriding)  (0) 2015.03.31
가변인자  (0) 2015.03.31
friend  (0) 2015.03.30