把自己的练习代码在此做个记录,希望对部分朋友有帮助。
至于结果,就不贴上来了,想研究的自己粘下来到vc6.0里面去试一下
看来 虚函数表 虚函数表指针 this指针 这几个之间关系还是比较微妙的。
下面一段话是一个高手写的,结合我的这段代码理解,会更有意思
高手曰:
编译器发现一个类中有虚函数,便会立即为此类生成虚函数表 vtable。虚函数表的各表项为指向对
应虚函数的指针。编译器还会在此类中隐含插入一个指针vptr(对vc编译器来说,它插在类的第一个位
置上)指向虚函数表。调用此类的构造函数时,在类的构造函数中,编译器会隐含执行vptr与vtable的
关联代码,将vptr指向对应的vtable。另外在调用类的构造函数时,
指向基础类的指针此时已经变成指向具体的类的this指针,这样依靠此this 指针即可得到正确的vtable。
如此才能真正与函数体进行连接,这就是动态联编,实现多态的基本原理。
下面 上代码:
// latebinding.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream.h>
class animal
{
public:
void sleep()
{
cout<<"animal sleep"<<endl;
}
virtual void breathe()
{
cout<<"animal breathe"<<endl;
}
};
class dog
{
void sleep()
{
cout<<"dog sleep"<<endl;
}
};
class fish:public animal
{
public:
fish()
{
cout<<"this指针的地址:" << (int*)(this) <<endl;
}
void breathe()
{
cout<<"this指针的地址:" << (int*)(this) <<endl;
cout<<"fish bubble"<<endl;
}
};
typedef void(*Fun)(void);
int main(int argc, char* argv[])
{
printf("Hello World!\n");
Fun pFun = NULL;
int i = sizeof(dog);
i = sizeof(animal);
animal aaaa;
fish fh;
cout << "虚函数表地址:" << (int*)(&fh) << endl;
cout << "虚函数表 - 第一个函数地址:" << (int*)*(int*)(&fh) << endl;
// Invoke the first virtual function
pFun = (Fun)*((int*)*(int*)(&fh));
pFun();
// dog dg;
// int j = sizeof(fh);
// j = sizeof(dg);
// animal *pAn=&fh; // 隐式类型转换
// pAn->breathe();//fish bubble
// fish *pFish=&fh; // 隐式类型转换
// pFish->breathe();//fish bubble
// animal an;
// animal bn;
// fish *pFh = (fish *)&an;
// pFh->breathe();//animal breath
return 0;
}