使用函数指针模拟C++多态
2024-09-04 03:50:06
#include <iostream>
using namespace std; class Base
{
public :
void display()
{
cout << "Base display" << endl;
} void (Base :: **VTable)();//指向虚表的函数指针
int a;
}; class Derived : public Base
{
public :
void display()
{
cout << "derived display" << endl;
}
}; void test(Base *pointer)
{
void (Base :: *pFunc)() = (void(Base :: *)())pointer->VTable[];
(pointer->*pFunc)();
} int main()
{
//多态是通过多余的存储空间存储了虚函数的地址,通过函数指针来实现虚函数的调用
//1.分配空间+4,成员变量从+4的位置开始了。最上面的控件保留一个指针。
//2.为该指针指向的地址分配一块存储空间
//3.将所有虚函数的地址存储到这块存储空间中,这个存储空间称为虚表 //初始化工作,也就是编译器帮我们做的事
Derived *derived = new Derived();
derived->VTable = (void(Base :: **)())new int[];
derived->VTable[] =(void(Base :: *)()) &Derived :: display;//初始化工作
test(derived); Base *base = new Base();
base->VTable = (void(Base :: **)())new int[];
base->VTable[] = (void(Base :: *)()) &Base :: display;
test(base);
system("pause");
return ;
}
基类如果不使用虚函数virtual构成多态的话,使用sizeof得到Base的大小为4,如下图(Base中的成员变量只有一个int a,使用32位编译器,如下代码中的基类,只是演示使用)
#include <iostream>
using namespace std; class Base
{
public :
void display()
{
cout << "Base display" << endl;
} int a;
}; class Derived : public Base
{
public :
void display()
{
cout << "derived display" << endl;
}
}; int main()
{
cout << "Base's size is " << sizeof(Base) << endl;
system("pause");
return ;
}
如果使用virtual构成虚函数,再使用sizeof测试基类的大小,会发现基类大小增加了4
#include <iostream>
using namespace std; class Base
{
public :
virtual void display()
{
cout << "Base display" << endl;
} int a;
}; class Derived : public Base
{
public :
void display()
{
cout << "derived display" << endl;
}
}; int main()
{
cout << "Base's size is " << sizeof(Base) << endl;
system("pause");
return ;
}
那这个 4byte的空间是什么东西?是干什么用?
经过向父类加入多个虚函数,测试之后发现还是只是增加4byte,那么只有指针可以做到。
这个指针是一个二级指针,指向一个虚表的地址,虚表中存储的是父类与子类同名函数的地址。(比较复杂,我也只能理解到这个地步,所以表达更是low)
/**********************************************************************************2017/7/20,以后有了更深的理解再继续更新******************************************************************************************/
最新文章
- js倒计时-倒计输入的时间
- ASP.NET Core中显示自定义错误页面-增强版
- PropertyMetadata和UIPropertyMetadata的一点区别
- C#搭建足球赛事资料库与预测平台(1) 基本介绍
- JS操作cookie以及本地存储(sessionStorage 和 localStorage )
- bzoj 1012 维护一个单调数列
- 基于Linux的oracle数据库管理 part3( 存储 网络 常用命令 )
- win8配置JDK
- Spring 捕捉校验参数异常并统一处理
- MySQL Router实现MySQL的读写分离
- phpexcel获取excel表格内容
- linux命令大全(1)
- The Mac App Store isn&#39;t working. How to fix?
- Android:getContext().getSystemService()
- mongoDB学习--建库、删库、插入、更新
- linux 不解压日志压缩包直接搜索里面的内容
- linux环境搭建前期配置
- JAVA容器-模拟ArrayList的底层实现
- [elk]logstash的grok匹配逻辑grok+date+mutate
- maven仓库添加本地jar