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

使用函数指针模拟C++多态的更多相关文章

  1. C用函数指针模拟重载 C++重载

    C中为什么不支持重载,即同一作用域内不允许出现同名函数? 我们都知道重载是c++面向对象的特性.c语言中是不存在的.所谓重载简单来说就是一个函数名可以实现不同的功能,要么输入参数不同或者参数个数不同, ...

  2. 关于函数指针与c++多态

    原文  https://www.cnblogs.com/zhchngzng/p/4013031.html 虚函数是实现多态的重要元素,请看: class A { public: void a0(){c ...

  3. c 结构体 & 函数指针模拟实现一个java class(类) 和方法

    闲来无事,纯粹练习. student.h #ifndef STUDENT_H_INCLUDED #define STUDENT_H_INCLUDED #include <memory.h> ...

  4. 使用函数指针和多态代替冗长的if-else或者switch-case

    在编程中,if-else和switch-case是很常见的分支结构,很少在程序中不用这些控制语句.但是不能否认,在一些场景下,由于分支结构过分长,导致代码不美观且不容易维护,在<重构>一书 ...

  5. C 语言实现多态的原理:函数指针

    C语言实现多态的原理:函数指针 何为函数指针?答案:C Programming Language. 能够查阅下,从原理上来讲,就是一个内存地址.跳过去运行相应的代码段. 既然如此,在运行时决定跳到哪个 ...

  6. C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)

    //多态的原理--虚函数指针--子类虚函数指针初始化 #include<iostream> using namespace std; /* 多态的实现原理(有自己猜想部分) 基础知识: 类 ...

  7. 2014 0416 word清楚项目黑点 输入矩阵 普通继承和虚继承 函数指针实现多态 强弱类型语言

    1.word 如何清除项目黑点 选中文字区域,选择开始->样式->全部清除 2.公式编辑器输入矩阵 先输入方括号,接着选择格式->中间对齐,然后点下面红色框里的东西,组后输入数据   ...

  8. 你必须知道的指针基础-7.void指针与函数指针

    一.不能动的“地址”—void指针 1.1 void指针初探 void *表示一个“不知道类型”的指针,也就不知道从这个指针地址开始多少字节为一个数据.和用int表示指针异曲同工,只是更明确是“指针” ...

  9. typedef 函数指针 数组 std::function

    1.整型指针 typedef int* PINT;或typedef int *PINT; 2.结构体 typedef struct { double data;}DATA,  *PDATA;  //D ...

随机推荐

  1. (转)docker run的--rm选项详解

    转:https://blog.csdn.net/taiyangdao/article/details/73076770 在Docker容器退出时,默认容器内部的文件系统仍然被保留,以方便调试并保留用户 ...

  2. linux记事工具:RedNotebook Lifeograph Kontact ThotKeeper

    Linux桌面有许多灵活而功能强大的日记工具,如支持标签.加密.多种日志模版和实时搜索.其中的优秀者包括: RedNotebook Lifeograph Kontact ThotKeeper

  3. HP Loadrunner 12.53的下载与安装

    HP Loadrunner 12.53的下载与安装   HP Loadrunner 12.53的下载:http://pan.baidu.com/s/1c23axHm HP Loadrunner 12. ...

  4. webservice 学习笔记 1

    Webservice----------->跨语言服务调用 (视频学习总结) 1-1.有OA系统 需要添加一个功能,登录之后显示天气情况 此时可以使用Webservice eg1: 气象局自己有 ...

  5. 干货 | Bokeh交互式数据可视化快速入门

    Bokeh简介 Bokeh是一款交互式可视化库,在浏览器上进行展示. Bokeh可以通过Python(或其它语言),快速便捷地为大型流数据集提供优雅简洁的高性能交互式图表. 安装 在python中有多 ...

  6. CentOS7下Docker与.net Core 2.2

    一.使用 yum 安装(CentOS 7下) Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker . 通过 una ...

  7. js数据处理-----数据拷贝

    一.理解深拷贝与浅拷贝 如下代码,把 a  的值赋给  b ,修改 b 的值会直接修改到  a 的值,这叫浅拷贝.(其实他们修改的是同一个对象) var a = [1,2,3,4,5]; var b ...

  8. elementUI table宽度自适应fit

    :fit='true' 或者直接为 fit

  9. C#用new和override来实现抽象类的重写区别

    一,抽象的实现 using System; using System.Collections.Generic; using System.Linq; using System.Text; namesp ...

  10. Spring学习笔记(6)——IoC的三种注入方式

    1.接口注入(不推荐) 2.构造器注入(死的应用) 3.getter,setter方式注入(比较常用) Type1 接口注入 我们常常借助接口来将调用者与实现者分离.如: public class C ...