读书人

虚函数表//俩个有关问题

发布时间: 2012-03-25 20:55:16 作者: rapoo

虚函数表//俩个问题

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。或者新定义的虚函数。

读书人网 >C++

热点推荐