我最近在搞虚函数表,以便更好地理解编译器/进程需要做什么来实现类和继承。
这就是我想要实现的目标:
我想编写自己的小 vtable,以便在对象上强制执行静态行为:
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 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 不再被读取???
额外信息:我在 openSuse 12.3 上使用 g++
最佳答案
vptr 指向 vtable 中的第三项。您可以从类转储中看到这一点:
vptr=((& A::_ZTV1A) + 16u)
或者通过将内存中的值与成员函数地址进行比较。
所以,您要修改的是前两项:
my_vtab[0] = &A::bar;
my_vtab[1] = &A::foo;
此外,不要使用成员函数指针构造新的 vtable,而应使用普通函数指针(甚至是 void*
)。例如。 :
typedef void (*func)();
或:
typedef void* func;
原因是成员函数指针已经处理虚拟成员函数,因此不适合作为 vtable 中的条目(有关更多信息,请参阅问题 Why the size of a pointer to a function is different from the size of a pointer to a member function? 例如)。
关于c++ - 了解 C++ vtable 和 RTTI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20222470/