观察CPP中虚函数的虚表

观察CPP中虚函数的虚表

Content #

#include <cstdio>
class A {
public:
    int a;
    virtual void foo() {
        printf("In A\n");
    }
};
class B : public A {
public:
    int b;
    virtual void foo() {
        printf("In B\n");
    }
};
int main() {
    A* obj = new B();
    obj->a = 1;
    obj->foo();
    return 0;
}

用objdump查看反汇编后的指令,关键部分如下:

mov -0x18(%rbp),%rax
movl $0x1,0x8(%rax) ;给a赋值
mov -0x18(%rbp),%rax
mov (%rax),%rax ;rax中内容为虚表地址
mov (%rax),%rax ;加载虚表指向的地址
mov -0x18(%rbp),%rdx
mov %rdx,%rdi  ;传入this指针
callq *%rax

还可以注意到,给a赋值时,a的起始位置离(%rax)多了8个字节,这就是为虚表留下的位置。如果去掉virtual修饰符,那么,给a赋值时,应该从(%rax)开始。

Viewpoint #

From #