关于虚函数表的个人总结
来源:互联网 发布:淘宝定制商品是什么 编辑:程序博客网 时间:2024/05/19 18:12
关于虚函数表的个人总结
1.虚函数表的创建:
一个类存在虚函数的时候,编译器会为这个类创建一个虚函数表,这个表由这个类的所有对象共同所有。
在创建这个类的类对象的时候将这个对象的前4个字节作为这项这个虚函数表的指针。即类对象的首地址中的内容存放的是虚函数表的地址。
虚函数表的首地址里面存放的是第一个虚函数的首地址,如果有多个虚函数,则第二个虚函数的地址即为第一个虚函数首地址加上偏移量,
地址如果用int*为单位表示的话偏移量加1,对于以16进制位表示的话则加4,(见下例,如果看着晕的话,不用看具体的,下面会有更加详细的解释).
----(int*)*(int*)*(int*)(&b)是第一个函数的地址,则第二个函数的地址是(int*)*((int*)*(int*)(&b)+1)或者(int*)*(int*)(*(int*)(&b)+4)----
运行结果如下:123456789101112131415161718192021222324252627#include<iostream>
using
namespace
std;
class
Base
{
public
:
virtual
void
f()
{
cout <<
"Base::f"
<< endl;
}
virtual
void
g()
{
cout <<
"Base::g"
<< endl;
}
virtual
void
h()
{
cout <<
"Base::h"
<< endl;
}
};
int
main()
{
Base b;
Base b1;
cout<<
"第一个类b的地址:"
<<(
int
*)(&b)<<endl;
cout<<
"第二个类b1的地址:"
<<(
int
*)(&b1)<<endl;
cout<<
"虚地址b:"
<<(
int
*)*(
int
*)(&b)<<endl;
cout<<
"虚地址b1:"
<<(
int
*)*(
int
*)(&b1)<<endl;
}
2.关于(int*)*(int*)*(int*)(&b)的解释
(int*)*(int*)*(int*)(&b)
(1)(&b)表示对对象取地址,返回的实际上是一个Base*类型的指针,也就是一个地址。
(2)(int*)(&b)强制将(Base*)类型转换成(int*)型指针,注意这里(int*)做的转换是从(Base*)到(int*)
实际上cout<<(&b)<<endl;与cout<<(int*)(&b)<<endl;的结果是一样的实际上都是指向的同一个地址,只是指针类型不同
(3)*(int*)(&b)表示去int型指针指向地址中的内容,即虚函数表地址的16进制位数表示,现在要注意了,这里的内容实际上int型的16进制数。
(4)(int*)*(int*)(&b)的第一个(int*)表示将取到的int型地址转换成地址,即虚函数表的地址,与(2)里面的(int*)的作用不一样。
比如下面的几条语句:
123int
* p;
//p=0x567890;
p=(
int
*)0x567890;
注释的地方是错误的关键就在于0x567890是一个十六进制数与地址无关,用(int*)可以将16进制数转化成地址,然后用指针p指向地址。
(5)*(int*)*(int*)(&b),表示取虚函数表中第一个地址中的内容,即虚函数表中存放的第一个函数的地址的十六进制数表示,是int型
(6)(int*)*(int*)*(int*)(&b),将表示第一个函数地址的16进制数转换成地址,即第一个函数的地址
(7)如果以地址为单位求下一个函数的地址则在地址后加4,如(int*)*(int*)(*(int*)(&b)+4)
如果以int*为单位的话求系一个函数地址则直接加1,如(int*)*((int*)*(int*)(&b)+1)
3.如何通过虚函数表进行函数调用。
现在在原来的代码中定义一个函数指针。
1
typedef
void
(*Fun)(
void
);
//如果不用Fun声明p函数指针的话可以直接写麻烦的式子:void(*p)(void)=(Fun)(int*)*((int*)*(int*)(&b)+1);
在main函数中
调用函数f:
1
2
3
Fun p=NULL;
p=(Fun)(
int
*)*(
int
*)*(
int
*)(&b);
p();
调用函数g
1
2
p=(Fun)(
int
*)*((
int
*)*(
int
*)(&b)+1);
//或者p=(Fun)(int*)*(int*)(*(int*)(&b)+4);
p();
调用函数h
1
2
p=(Fun)(
int
*)*((
int
*)*(
int
*)(&b)+2);
//或者p=(Fun)(int*)*(int*)(*(int*)(&b)+8);
p();
结果:
- 关于虚函数表的个人总结
- 关于虚函数表的个人总结
- 关于malloc\free函数的用法个人总结
- 我的虚函数个人总结
- 关于INSTALL_FAILED_NO_MATCHING_ABIS.的个人总结
- 关于虚函数的总结
- 关于matlab中图像处理最基本的函数的个人总结
- C语言基础知识(个人简单总结的关于变量和函数方面)
- 关于sql的一些个人总结
- 关于集合类的个人总结
- 关于linux内核中断的个人总结
- 关于编程方面的个人总结
- 关于LBS项目开发的个人总结
- 关于LBS项目开发的个人总结
- 关于vim的一些个人总结
- 关于WCF操作重载的个人总结
- 关于Mapper、Reducer的个人总结
- 关于技能与个人的发展总结
- mysql权限说明
- CSS3 Gradient
- mysql5.5 主从复制 (触发器,函数,存储引擎,事件处理)说明
- 二分-hdu-4768-Flyer
- D3D9 Samples(12)--CompiledEffect
- 关于虚函数表的个人总结
- MySQL5.5 主从复制
- linux内存使用正确理解
- css mask, WebKit Image Wipes
- MySQL5.5 自动分区脚本
- MySQL 5.5 分区性能测试之索引使用情况
- ubuntu下用apt-get install 安装软件时出现 initramfs-tools错误
- 面向对象的深复制与浅复制
- JAVA中JNI的简单使用