反反复复
分类: C/C++
2013-03-13 16:58:30
http://www.cnblogs.com/Ripper-Y/archive/2012/05/15/2501930.html
多态性可分为两类:静态多态和动态多态。函数重载和运算符重载实现的多态属于静态多态,动态多态性是通过虚函数实现的。
每个含有虚函数的类有一张虚函数表(vtbl),表中每一项是一个虚函数的地址, 也就是说,虚函数表的每一项是一个虚函数的指针。
没有虚函数的C++类,是不会有虚函数表的。
两张图:
简单例子:
#include
#include
using namespace std;
class base
{
virtual void f(){cout<<"base::f"<
typedef void (*pfun)();
void main()
{
DWORD w=0x4011e0; //虚函数表第一项的内容,也就是第一个虚函数的地址
pfun fun=NULL;
base b;
base *pbase=&b;
fun=(pfun)w;
fun(); //调用第一个虚函数
}
查看对象b在内存中:
查看虚函数表:
虚函数表的指针4个字节大小(vptr),存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。
虚函数表的结束标志在不同的编译器下是不同的。在VC6.0下,这个值是NULL,如图:
另一个例子:
#include
using namespace std;
class base
{
virtual void f(){cout<<"base::f"<
class Derive : public base
{
public:
Derive(){};
virtual void f() { cout << "Derive::f" << endl; }
virtual void g() { cout << "Derive::g" << endl; }
};
typedef void(*pfun)();
void main()
{
pfun fun=NULL;
Derive d;
base *p=&d;
fun=(pfun)**((int**)p);
fun(); //调用第一个虚函数
fun=(pfun)*(*((int**)p)+2);
fun(); //调用第三个函数
}
查看对象d在内存中:
多重继承:
有几个父类,就有几个vtab和vptr
#include