虚函数表的空间有关问题
虚函数表的空间问题
小弟写一简单的测试程序如下,主要目的是测试当类中有虚函数存在时的内存分配情况:
#include <iostream.h>
class test
{
public:
virtual void print()
{
cout < < "Print from test " < < endl;
}
};
class test2:public test
{
public:
virtual void pp()
{
cout < < "PP from test2 " < < endl;
}
virtual void print()
{
cout < < "Print from test2 " < < endl;
}
};
class test3:public test2
{
public:
virtual void pp()
{
cout < < "PP from test3 " < < endl;
}
virtual void print()
{
cout < < "Print from test3 " < < endl;
}
};
void main()
{
test *pt,t;
test2 *ptt,tt;
test3 *pttt,ttt;
cout < < "Size of t = " < < sizeof(t) < < endl;
cout < < "Size of tt = " < < sizeof(tt) < < endl;
cout < < "Size of ttt = " < < sizeof(ttt) < < endl;
tt.pp()
ttt.pp();
t.print();
tt.print();
ttt.print();
pt = &tt;
ptt = &ttt;
pttt = &ttt;
pt-> print();
ptt-> print();
pttt-> print();
ptt-> pp();
pttt-> pp();
}
它的显示结果为:
Size of t = 4
Size of tt = 4
Size of ttt = 4
PP from test2
PP from test3
Print from test
Print from test2
Print from test3
Print from test2
Print from test3
Print from test3
PP from test3
PP from test3
我们知道,当类中存在虚函数里.则编译器会在编译期自动的给该类生成一个函数表.并在所有该类的对像中放入一个隐式变量如_vfprt,该变量是一个指针变量,它的值指向那个类中的由编译器生成的虚函数表.
在调试的状态下.小弟查看调试器中的内存状态.发现.如test的子类test2的对像tt中只有指针变量_vfptr存在,该变量所指向的类test的虚函数表中只有类test2的print()函数的地址.这里并没有子类中的虚函数pp()的地址,小弟认为这应该就是为什么 "指向子类的父类的引用或指针不能访问父类中并不存在的函数或成员 "的规则限制.
但有趣的是.既然在虚表中不存在虚函数pp()的地址.那最少子类也应该生成一个类似的表以存放那些在父类中不存的虚函数吧.这样也符合 "当类中有虚函数里编译器会自动为该类生成虚函数表,并在所有该类对像中插入一个指向该表的指针. "的规则啊...但从调试器的角度来看,好像什么都没有...没有新的虚函数表生成,也没有看到pp()函数的存在.
这样问题就产生了.看我的测试显示的结果,显然.在子类的子类test3中多态的性质还是被应用了出来(如pp()函数的调用).
这不是很奇怪,test3的父类的虚表中并不存在pp()的地址.那么在其子类test3中的多态又是怎么实现的呢?
敬请各位大大不吝指教......
------解决方案--------------------
test2的_vfptr中,pp的值可能在print后面,楼主检查过没有?
小弟写一简单的测试程序如下,主要目的是测试当类中有虚函数存在时的内存分配情况:
#include <iostream.h>
class test
{
public:
virtual void print()
{
cout < < "Print from test " < < endl;
}
};
class test2:public test
{
public:
virtual void pp()
{
cout < < "PP from test2 " < < endl;
}
virtual void print()
{
cout < < "Print from test2 " < < endl;
}
};
class test3:public test2
{
public:
virtual void pp()
{
cout < < "PP from test3 " < < endl;
}
virtual void print()
{
cout < < "Print from test3 " < < endl;
}
};
void main()
{
test *pt,t;
test2 *ptt,tt;
test3 *pttt,ttt;
cout < < "Size of t = " < < sizeof(t) < < endl;
cout < < "Size of tt = " < < sizeof(tt) < < endl;
cout < < "Size of ttt = " < < sizeof(ttt) < < endl;
tt.pp()
ttt.pp();
t.print();
tt.print();
ttt.print();
pt = &tt;
ptt = &ttt;
pttt = &ttt;
pt-> print();
ptt-> print();
pttt-> print();
ptt-> pp();
pttt-> pp();
}
它的显示结果为:
Size of t = 4
Size of tt = 4
Size of ttt = 4
PP from test2
PP from test3
Print from test
Print from test2
Print from test3
Print from test2
Print from test3
Print from test3
PP from test3
PP from test3
我们知道,当类中存在虚函数里.则编译器会在编译期自动的给该类生成一个函数表.并在所有该类的对像中放入一个隐式变量如_vfprt,该变量是一个指针变量,它的值指向那个类中的由编译器生成的虚函数表.
在调试的状态下.小弟查看调试器中的内存状态.发现.如test的子类test2的对像tt中只有指针变量_vfptr存在,该变量所指向的类test的虚函数表中只有类test2的print()函数的地址.这里并没有子类中的虚函数pp()的地址,小弟认为这应该就是为什么 "指向子类的父类的引用或指针不能访问父类中并不存在的函数或成员 "的规则限制.
但有趣的是.既然在虚表中不存在虚函数pp()的地址.那最少子类也应该生成一个类似的表以存放那些在父类中不存的虚函数吧.这样也符合 "当类中有虚函数里编译器会自动为该类生成虚函数表,并在所有该类对像中插入一个指向该表的指针. "的规则啊...但从调试器的角度来看,好像什么都没有...没有新的虚函数表生成,也没有看到pp()函数的存在.
这样问题就产生了.看我的测试显示的结果,显然.在子类的子类test3中多态的性质还是被应用了出来(如pp()函数的调用).
这不是很奇怪,test3的父类的虚表中并不存在pp()的地址.那么在其子类test3中的多态又是怎么实现的呢?
敬请各位大大不吝指教......
------解决方案--------------------
test2的_vfptr中,pp的值可能在print后面,楼主检查过没有?