#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,以后有了更深的理解再继续更新******************************************************************************************/

最新文章

  1. js倒计时-倒计输入的时间
  2. ASP.NET Core中显示自定义错误页面-增强版
  3. PropertyMetadata和UIPropertyMetadata的一点区别
  4. C#搭建足球赛事资料库与预测平台(1) 基本介绍
  5. JS操作cookie以及本地存储(sessionStorage 和 localStorage )
  6. bzoj 1012 维护一个单调数列
  7. 基于Linux的oracle数据库管理 part3( 存储 网络 常用命令 )
  8. win8配置JDK
  9. Spring 捕捉校验参数异常并统一处理
  10. MySQL Router实现MySQL的读写分离
  11. phpexcel获取excel表格内容
  12. linux命令大全(1)
  13. The Mac App Store isn&#39;t working. How to fix?
  14. Android:getContext().getSystemService()
  15. mongoDB学习--建库、删库、插入、更新
  16. linux 不解压日志压缩包直接搜索里面的内容
  17. linux环境搭建前期配置
  18. JAVA容器-模拟ArrayList的底层实现
  19. [elk]logstash的grok匹配逻辑grok+date+mutate
  20. maven仓库添加本地jar

热门文章

  1. 使用DataV制作实时销售数据可视化大屏(实验篇)
  2. codeforces 582A GCD Table
  3. Java学习之多线程(线程安全问题及线程同步)
  4. js设置cookies
  5. [Fw]中断的初始化
  6. HDU 3622 Bomb Game(2-sat)
  7. git help
  8. Bata冲刺第三天
  9. 用私有构造器或者枚举类型强化SingleTon(单例)属性
  10. React 滚动事件