使用虚函数表指针来调用虚函数遇到的问题

Posted ybossy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用虚函数表指针来调用虚函数遇到的问题相关的知识,希望对你有一定的参考价值。

使用虚函数表指针来调用虚函数遇到的问题

定义一个Father类,代码如下:

class Father {
public:
virtual void func1() {cout << "Father::func1" << endl;}
virtual void func2() { cout << "Father::func2" << endl; }
virtual void func3() { cout << "Father::func3" << endl; }
void func4() { cout << "非虚函数:Father::func4" << endl; }
public:
int x = 200;
int y = 300;
static int z;
};

typedef void (*func_t)(void);

int main(void){

Father father;


cout << "对象father地址:" <<(int)&father << endl;
int* vptr = (int*)*(int*)(&father);//函数指针,int*类型
cout << "vptr:" << vptr << endl;

//((void (*)(void))vptr)(); wrong

((void(*)(void))*(vptr))();

((func_t) * (vptr + 0))();
((func_t) * (vptr + 1))();
((func_t) * (vptr + 2))();

? return 0;

}

解释:对father对象取地址得到一个地址,因为地址里面存储的值是一个虚函数表指针,而函数指针占四个字节,因此将地址转为(int *)类型以告诉编译器内存大小,再解引得到虚函数表指针,最后再转为(int *)类型,得到了虚函数表的指针,此时为(int *)类型,最后通过这个int *类型的指针来调用虚函数,如何调用?先得转变指针的类型,因为指针指向的虚函数的返回值是空。

因此定义一个类型

typedef void(*func_t)(void);

然后写代码((func_t) * (vptr + 0))();即可调用虚函数,即先解引虚函数表的指针,得到虚函数的指针,这里注意:区别虚函数表指针与虚函数指针!不然会发生错误,这里需要经过两次解引用!第一次是对&father解引得到虚函数表指针,然后是对虚函数表指针解引得到虚函数指针。

所以不用自定义类型来调用虚函数也很明白了,代码应该这样子写
:((void( *) (void) )) *(vptr))();
千万不要像我之前那样调用((void( *) (void) ))(vptr))(); 将虚函数表指针与虚函数指针混为一谈,闹了笑话。

主要还是理解虚函数表指针这个概念吧!

以上是关于使用虚函数表指针来调用虚函数遇到的问题的主要内容,如果未能解决你的问题,请参考以下文章

C++之:虚函数表

虚函数表指针与多态

虚函数表指针与多态

static函数如何调用虚函数

虚函数逆向分析

虚函数和基类中的this指针的问题!