2013-11-26 4 views
1



요즘 위해 vtable을 만지작되었다 더 나은 컴파일러/프로세스가 클래스와 상속을 구현하기 위해 수행해야하는 것을 이해합니다.
이해 C++ vtable을 및 RTTI

class A { 
public: 
    virtual void foo() { cout << "A.foo()" << endl; } 
    virtual void bar() { cout << "A.bar()" << endl; } 
}; 

class B : public A { 
public: 
    void foo() { cout << "B.foo()" << endl; } 
    void bar() { cout << "B.bar()" << endl; } 
}; 

typedef void (A::*func)(); 

int main() { 
    A& b_as_a = *(new B()); 
    long* p = (long*)(&b_as_a); 
    func* vtab = (func*)(p[0]); 

    b_as_a.foo(); 
    b_as_a.bar(); 

    func* my_vtab = new func[4]; 

    my_vtab[0] = vtab[0]; // \ I added these lines in step two after i got an 
    my_vtab[1] = vtab[1]; ///access violation 
    my_vtab[2] = &A::bar; 
    my_vtab[3] = &A::foo; 

    p[0] = (long)(my_vtab); 

    b_as_a.foo(); 
    b_as_a.bar(); 

    delete[] my_vtab; 
    delete &b_as_a; 

    return EXIT_SUCCESS; 
} 

여기 g++ -std=c++11 -fdump-class-hierarchy의 덤프 :
내가 객체에 정적 동작을 강제하기 위해 내 자신의 작은 VTABLE을 쓰고 싶다 :

내가 성취하려고했던 것입니다

Vtable for A 
A::_ZTV1A: 4u entries 
0  (int (*)(...))0 
8  (int (*)(...))(& _ZTI1A) 
16 (int (*)(...))A::foo 
24 (int (*)(...))A::bar 

Class A 
    size=8 align=8 
    base size=8 base align=8 
A (0x0x7f40b60fe000) 0 nearly-empty 
    vptr=((& A::_ZTV1A) + 16u) 

Vtable for B 
B::_ZTV1B: 4u entries 
0  (int (*)(...))0 
8  (int (*)(...))(& _ZTI1B) 
16 (int (*)(...))B::foo 
24 (int (*)(...))B::bar 

Class B 
    size=8 align=8 
    base size=8 base align=8 
B (0x0x7f40b60dfbc8) 0 nearly-empty 
    vptr=((& B::_ZTV1B) + 16u) 
    A (0x0x7f40b60fe060) 0 nearly-empty 
     primary-for B (0x0x7f40b60dfbc8) 


이 작동하지 않았다가 ... 그래서 나는 조금 연구.
이 게시물을 찾았습니다 : What is the first (int (*)(...))0 vtable entry in the output of g++ -fdump-class-hierarchy?
vtable의 처음 두 항목을 설명합니다. 첫 번째 항목이 무엇을하는지 이해하지만 두 번째 항목에 대해 알고있는 것은 그것이 클래스 정보에 대한 포인터의 일부라는 것입니다.
그것이 작동하지 않는 이유입니다. 남아

질문 :
은 VTABLE에서 두 번째 항목은 funktionpointers은 아래에 더 이상 무엇을 읽을되지 않는 않는 ???


추가 정보 : 내가 오픈 수세 12.3

+0

질문의 내용을 이해하는 데 문제가 있습니다. 당신이 원하는 것을 더 설명 할 수 있습니까? –

답변

1

VTABLE의 세 번째 항목에이 vptr에 ++ g을 사용하고 있습니다. 클래스 덤프에서 볼 수 있습니다 :

vptr=((& A::_ZTV1A) + 16u) 

또는 구성원 함수 주소와 메모리 내 값을 비교하여 볼 수 있습니다.

my_vtab[0] = &A::bar; 
my_vtab[1] = &A::foo; 

또한, 멤버 함수 포인터와 새로운 VTABLE을 구성하지 않고, (심지어 또는 void*) 일반 함수 포인터와 :

그럼, 수정할 것은 처음 두 항목입니다. 예 : :

typedef void (*func)(); 

이나 : 그 이유는 그 멤버 함수 포인터가 이미 가상 멤버 함수를 처리하고, 따라서 더 많은 정보에 대한 VTABLE (의 항목으로서 적합하지 않은 것이다

typedef void* func; 

, 참조 예 : Why the size of a pointer to a function is different from the size of a pointer to a member function?).

+0

좋아, 그 덕분에, 고마워! – Ch33f