首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

求教一些关于虚函数的有关问题

2012-04-25 
求教一些关于虚函数的问题。C/C++ codeclass A{public:virtual void fa() { cout A::f endl }}

求教一些关于虚函数的问题。

C/C++ code
class A{public:    virtual void fa() { cout << "A::f" << endl; };};


首先,我知道A有一个VPTR,指向它的虚函数表。

我的问题是,对于A的所有对象,例如A a1, A a2,这个a1和a2的VPTR是否和A的VPTR是同一个值,指向同一个虚函数表?还是对于每个对象,都有一个虚函数表?

问题2,Thinking in C++上有这么一句话:“如果一个函数在基类中被声明为virtual,则在所有的派生类中它都是virtual”,是什么意思呢?

如果我这样实现B,

C/C++ code
class B : public A{public:    void fa() { cout << "B::f" << endl; };};


那么B是派生类,但B中的fa不是virtual啊。

问题3,对于每一个类来说只有一个VPTR,但对于C,

C/C++ code
class C : public A{public:    void fa() { cout << "C::f" << endl; };    virtual fc() { cout << "C::f" << endl; };};


C有一个VPTR指向它自己的虚函数,但它是怎么找到A中的虚函数表的?是否表示C中还存了一个A的VPTR,可是sizeof(C)为4,表示只有一个VPTR,不太理解。

[解决办法]
我的问题是,对于A的所有对象,例如A a1, A a2,这个a1和a2的VPTR是否和A的VPTR是同一个值,指向同一个虚函数表?还是对于每个对象,都有一个虚函数表?

a1,a2的vptr指向同一个表

问题2,Thinking in C++上有这么一句话:“如果一个函数在基类中被声明为virtual,则在所有的派生类中它都是virtual”,是什么意思呢?

就是说派生类同名的 参数相同的函数默认也是virtual的
[解决办法]
C有一个VPTR指向它自己的虚函数,但它是怎么找到A中的虚函数表的?是否表示C中还存了一个A的VPTR,可是sizeof(C)为4,表示只有一个VPTR,不太理解。

c有一个自己的虚函数表 C类型的对象里面的vptr只会指向C自己的虚函数表。
[解决办法]
1. 两个对象的虚函数表的地址应该是不一样的,但是两个对象对应的虚函数地址(及虚函数表中某项所指向的内容)是一样的。参考下面的代码:
C/C++ code
#include <iostream>using namespace std;class A{public:    virtual void fa()    {         cout << "A::f" << endl;     }};// 定义一个函数指针类型typedef void (*fun)();// 获取一个对象中的虚函数指针fun getVirtualFunction(A* obj, unsigned long offset){    // 1. obj就是类A的对象地址,而vfptr总是在一个对象内存布局的最前面,因此obj其实也就是vfptr的开始;    // 2. 在32-bit的操作系统中,地址空间也是32-bit的,我们知道long是4Bytes,因此(unsigned long*)obj就是vfptr    //    指针(即包括obj及其后面3个Bytes的内容,unsigned long*从本质上说,就是限定包括obj及其后面3个Bytes的    //    内容作为vfptr指针);    // 3. *(unsigned long*)obj,就是vfptr指针中的内容,其中前4Bytes也就是virtual table的起始地址;    // 4. (unsigned long *)(*(unsigned long*)obj)取得virtual table的4Bytes地址,也就是虚函数表中第一项,它也    //    是一个指针,这个指针指向第一个虚函数的地址,也就是说该指针的内容为第一个虚函数的指针;如果offset = 1,    //    那么(unsigned long *)(*(unsigned long*)obj) + offset就是虚函数表中第二项,它是一个指向第二个虚函数地    //    址的指针,依此类推;    unsigned long* vtbl = (unsigned long *)(*(unsigned long*)obj) + offset;    // 5. 承4,如果vtbl是虚函数表中第一项,那么*(vtbl)就是第一个虚函数的指针,通过(fun)转化成为一个无参数,返回    //    值类型为void的函数指针,以此类推。    fun p = (fun) *(vtbl);    return p;}int main(int argc, char** argv){    A a1;    A a2;    cout << &a1 << endl;    // a1的虚函数表的地址,其实也就是a1的this指针    cout << &a2 << endl;    // a2的虚函数表的地址,其实也就是a2的this指针    cout << getVirtualFunction(&a1, 0) << endl;        // 对象a1的虚函数fa的指针    cout << getVirtualFunction(&a2, 0) << endl;     // 对象a2的虚函数fa的指针    return 0;} 

热点排行