探究C++多态实现原理
探究C++多态实现原理
在之前的博客中讲到了如何使用C++多态的性质,实现面对对象的程序设计。
在这一篇文章中将会从多态的实现原理,_vfptr 以及多态类的内存构建模型上来探究C++多态的实现过程。
从以下代码来讨论:
#include <iostream>
using namespace std;
typedef void(*VIRTUALL)();
class Person
{
public:
virtual void fun1()
{
cout << endl << "this is Person fun 1" << endl;
}
virtual void fun2()
{
cout << endl << "this is Person fun 2" << endl;
}
virtual void fun3()
{
cout << endl << "this is Person fun 3" << endl;
}
};
class Boss :public Person
{
public:
virtual void fun1()
{
cout << endl << "this is Boss fun 1" << endl;
}
virtual void fun2()
{
cout << endl << "this is Boss fun 2" << endl;
}
virtual void fun3()
{
cout << endl << "this is Boss fun 3" << endl;
}
};
int main()
{
Person p;
Boss b;
return 0;
}
在此段代码当中,我们为每个类定义了三个虚函数,并且对他们进行重写,如何监视这两个类的成员。
运行起来打开监视
发现每个类都有一个 _vfptr (virtual function pointer)指针,指向的是一个数组的首地址,这个数组中存放着函数名,也就是函数地址。
在C++中,一个指针类型的大小代表这个指针从首地址开始能往后面读到的字节数,比如 char* 类型的指针可以从首地址往后读一个字节大小, int * 类型的指针 能从首地址往后读四字节的大小,以此类推,我们可以将 类对象进行强制类型转换,因为类对象的前四个字节解引用指向的是描述的虚函数数组的地址空间,所以将其进行 int * 类型的地址转换,可以证明我们的猜测。
代码如下:
#include <iostream>
using namespace std;
typedef void(*VIRTUALL)();
class Person
{
public:
virtual void fun1()
{
cout << endl << "this is Person fun 1" << endl;
}
virtual void fun2()
{
cout << endl << "this is Person fun 2" << endl;
}
virtual void fun3()
{
cout << endl << "this is Person fun 3" << endl;
}
};
class Boss :public Person
{
public:
virtual void fun1()
{
cout << endl << "this is Boss fun 1" << endl;
}
virtual void fun2()
{
cout << endl << "this is Boss fun 2" << endl;
}
virtual void fun3()
{
cout << endl << "this is Boss fun 3" << endl;
}
};
void PrintVirtual(int * _ptr)
{
for (int i = 0; ; ++i) {
if (_ptr[i] == 0)
break;
else
{
VIRTUALL* fd = (VIRTUALL*)(_ptr+i);
(*fd)();
}
}
}
int main()
{
Person p;
Boss b;
PrintVirtual((int*)(*((int*)&p)));
PrintVirtual((int*)(*((int*)&b)));
return 0;
}
实例化出来的类对象 p 和 b,我们先对其进行取地址操作,再强制类型转换为 int * 类型,这样他的前四个字节的就出来了,然后对地址进行解引用,可以得出虚表的首地址,再对其转换为 int *类型,可以实现每次四字节的访问。再对这每次的访问函数进行调用,就明白了其内存模型的构建方式。
运行结果:
内存构建方式: