虚函数原理1

来源:互联网 发布:闲鱼申请淘宝介入15天 编辑:程序博客网 时间:2024/06/06 19:31

部分参考:http://blog.csdn.net/devilkin64/article/details/5939613

虚函数表的建立是取决于定义类的时候是否包含虚函数,如果有类函数/ 方法声明为虚,则改类会建立一张虚表.在网上找到一个牛人用汇编的方法论证虚 表是存放在常量区内(具体论证就省略,否则就扯远了). 继承类会同样建立一张虚表,并将覆盖虚表中父类虚函数的地址.
在编译阶段,编译器为每个包含虚函数的类创建一个虚表,这个类的所有对象中的虚表指针,都指向这同一份虚表;一般虚表指针放在对象的开始位置;
虚函数表是在代码编译生成,程序载入内存的时候,放在内存常量区. 
虚函数指针是在对象建立时由构造函数生成并保存于对象地 址首部.
虚函数指针:虚函数指针是在实例化对象 的时候由构造函数生成的指向虚表的指针.放在对象地址的首位. 下面代码用于显 示虚表及虚表指针.

class base{public:int a;virtual void Print(){cout<<"in base print\n";}};class d1:public base{public:void Print(){cout<<"in d1 print\n";}void d1Print(){cout<<"d1 self print \n";}};class d2:public d1{public:void Print(){cout<<"in d2 print\n";}void d2Print(){cout<<"d2 self print \n";}};typedef void (*pfun)();int main(){base *md2 = new d2;md2->Print();d1 *md1 = new d2;md1->Print();//上面两个例子说明,虚函数具有向下传递的特性;只要在最开始的基类中定义虚函数,则其他所有的子孙类都默认是虚函数int *p2 =(int *) md2;//md2本来是指向对象的一个指针,将此指针转换为指向一个int数组的指针,这样就能像访问数组一样访问对象里面的数据cout<<*p2<<endl;//*p2是指放在对象md2中第一个位置的元素的值,这个值就是虚表的地址p2  =(int *)(*p2);//*p2是虚表的地址,也就是指虚表的指针,我们要把虚表也表示成数组的形式,把指向虚表的指针转换为指向一个Int数组的指针printf("%x\n",p2);//cout<<p2<<endl;//printf("%d\n",p2);//上面三个输出的值都是相等的,只不过是十进制或者十六进制表示的不同(pfun(*p2))();int *p1 = (int *) md1;cout<<*p1<<endl;//上面所有的输出都是显示的是类d2的虚表的地址,也就是说不管类有多少个对象,但是虚表只有一份/*int i =0;int *p = &i;cout<<&i<<" "<<p<<endl;*/delete md1;delete md2;}




原创粉丝点击