虚函数表//俩个问题C/C++ code#include iostreamusing namespace stdtypedef void (*fun) (void)class
虚函数表//俩个问题
C/C++ code#include <iostream>using namespace std;typedef void (*fun) (void);class A {public: virtual void foo (void) { cout << "A::foo() invoked" << endl; } virtual void bar (void) { cout << "A::bar() invoked" << endl; }};class B : public A{public: void foo (void) { cout << "B::foo() invoked" << endl; }};int main(){ A a; fun* p = *(fun**)&a;//中fun**是什么类型呀?&a换成a为什么取不到? cout << "A::p[0] = " << (void*)p[0] << endl; (p[0]) (); cout << "A::p[1] = " << (void*)p[1] << endl; (p[1]) ();}
[解决办法]LZ你的代码被我修改后的情况:
#include <iostream>
using namespace std;
typedef void (*fun) (void);
class A {
public:
virtual void foo (void)
{
cout << "A::foo() invoked" << endl;
}
virtual void bar (void)
{
cout << "A::bar() invoked" << endl;
}
public:
intnMember;
};
class B : public A{
public:
void foo (void)
{
cout << "B::foo() invoked" << endl;
}
};
int main()
{
int t = 2;
int* pt = &t;
int** ppt = &pt;
cout << "地址:" << &t << " " << &pt << " " << &ppt<< endl;
cout << "值:" << t << " " << pt << " " << ppt << endl;
A a;
int* pVptr = (int*)(&a);
fun* pF = (fun*)*pVptr;
cout << "A::p[0]" << (fun*)pF[0] << endl;
cout << "A::p[1]" << (fun*)pF[1] << endl;
pF[0]();
pF[1]();
fun* p = *(fun**)&a;//中fun**是什么类型呀?&a换成a为什么取不到?
cout << "A::p[0] = " << (void*)p[0] << endl;
//cout << "A::p[0] = " << (int*)p[0] << endl;
(p[0]) ();
cout << "A::p[1] = " << (void*)p[1] << endl;
//cout << "A::p[1] = " << (int*)p[1] << endl;
(p[1]) ();
system("pause");
}
编译结果如下:
首先,LZ你必须理解C++内部虚函数指针的构造。以及C++如何解析
Int *pt,和A* pa的。
对于int * pt,C++会把pt的值(也就是*pt,本例为0018FF28)开始的一段内存开始的4个字节解析为一个int型,得到2。
同理解析ppt,首先查看ppt的值(也就是*ppt,本例为0018FF1C)开始的一段内存,也解析4个字节,区别的是这里把这4个字节作为地址来解析。也就是&pt ==0018FF1C。和上面的结果一致吧。
注:在C++中,整型和指针类型都占4个字节。
好了,下面我们分析虚函数指针。
我先把Inside C++ Object中的虚函数表画出来,帮助你理解。
这里创建了一个对象a,如果你cout << a << endl;
是会出错的,为什么呢?因为C++不知道如何解析这个对象a。但是cout << t << endl;这里t是我们定义的整型。
所以我们需要获取vptr的值,这里int*pVptr = (int*)&a;这里得到的值就是*pVptr占用内存块的值,但是如何解析是个问题。
Fun* pF = (fun*)*pVptr;
这该如何理解呢?请看,所以*pVptr得到的就是vptr的值。然后我们要解析右边虚函数表的。(fun*)*pVptr是强制把这块内存转换为一个指针,指向虚函数表。
该表每一项都是一个指针,指向了实际的函数。
所以p[0]指向foo,p[1]指向bar。
我们还知道,函数名就是函数的地址,p[0]存的也是地址。
所以pF[0](0)访问的是foo函数。
注:
1.vptr下面的省略号是成员变量,如果没定义就没有。
2.virtual table下面的省略号是其他的type_info。或者新定义的虚函数。