#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. flask实现异步任务

    最近在开发同步mysql数据到redis的接口,因为数据同步涉及各种增删查改,如果用同步实现,可能回造成连接超时.堵塞,所以,使用python实现异步任务. 代码实现from flask import ...

  2. 如何保存android app日志

    android 手机日志保存方法如下: 前置条件:已安装adb 1,手机usb连接电脑,打开USB调试模式(注意仅连接一台手机设备) 2,win+R输入cmd打开命令窗口,输入指令:adb devic ...

  3. 如何使用iText制作中文PDF

    1. 下载itextpdf.jar 基础包:http://jaist.dl.sourceforge.net/project/itext/iText/iText5.5.2/itext-5.5.2.zip ...

  4. Android深度探索-卷1第二章心得体会

    这章介绍了搭建Android开发环境的的搭建,主要是在Linux上搭建Android开发环境总体来说因为都是在Linux下开发的,so,只介绍了在Linux环境下的搭建在搭建过程中全是命令操作,和Wi ...

  5. CommonJS规范 by ranyifeng

    1,概述 CommonJS是服务器端模块的规范,Node.js采用了这个规范. 根据CommonJS规范,一个单独的文件就是一个模块.加载模块使用require方法,该方法读取一个文件并执行,最后返回 ...

  6. linux下对rpm源码手工打补丁

    前言 通常情况rpm包组件管理方式下的linux环境,常用打补丁的方式只有一种:修改spec文件定义的Patch和patch字段,其实spec文件中调用的底层命令还是patch.  因为业务需要要编译 ...

  7. Intellij Idea乱码解决方案都在这里了

    乱码场景 使用Intellij Idea经常遇到乱码问题,可以总结为以下几类乱码的场景. 1.工程代码乱码. 2.main方法运行,控制台乱码. 3.tomcat运行,控制台乱码. 解决方案 1.工程 ...

  8. NOIP2015D1T2 信息传递

    题目描述 有 n 个同学(编号为 1 到 n )正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为 i 的同学的信息传递对象是编号为 Ti​ 的同学. 游戏开始时,每人都只 ...

  9. WPF 基本图形

    一.WPF的基本图形 WPF图形的基类是Shape,所有的wpf图形类都是继承于Shape.Height,Width等决定它所处的面积,位置等,在没有设置图形宽高的情况,坐标位置为所在的容器的坐标,设 ...

  10. thinkphp5 自动注册Hook机制钩子扩展

    Hook.php 文件已更新1.修复在linux环境下类的 \ 在basename 下无法获取到类名的问题2.修复linux 环境下无法使用hook::call 调用失败问题 请先安装thinkphp ...