C++中的虚函数的作用主要是实现了多态,本人通过代码验证的方式了解虚表的结构及在多种继承方式下通过虚表访问子类函数。验证结果如下:

  1)无虚函数覆盖的一般继承:可以通过子类的虚表访问父类的函数

  2)虚函数重载父类的虚表:子类重载的虚函数会覆盖父类的函数

  3)多重继承无重载的虚表:多重继承子类的虚表就像一张二维表,可以像遍历二维数组一样访问所有父类函数

  4)多重继承有重载的虚表:所有父类被重载的虚函数都会被覆盖

  5)父类指针访问子类自己的虚函数

  6)公有继承访问父类非公有虚函数

 #include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std;
// 基类
class Base
{
public:
virtual void Fun1()
{
cout << "Base::Fun1" << endl;
}
virtual void Fun2()
{
cout << "Base::Fun2" << endl;
}
virtual void Fun3()
{
cout << "Base::Fun3" << endl;
} private: }; // 无重载继承类
class Derive :Base
{
public:
virtual void DeriveFun1()
{
cout << "Derive::Fun1" << endl;
}
virtual void DeriveFun2()
{
cout << "Derive::Fun2" << endl;
}
virtual void DeriveFun3()
{
cout << "Derive::Fun3" << endl;
}
}; // 重载继承类
class Override :public Base
{
public:
virtual void Fun1()
{
cout << "Override::Fun1" << endl;
}
virtual void OverrideFun2()
{
cout << "Override::Fun2" << endl;
}
virtual void OverrideFun3()
{
cout << "Override::Fun3" << endl;
}
}; // 多重继承无重载
class Base1
{
public :
virtual void Fun1()
{
cout << "Base1::Fun1" << endl;
}
virtual void Fun2()
{
cout << "Base1::Fun2" << endl;
}
virtual void Fun3()
{
cout << "Base1::Fun3" << endl;
}
};
class Base2
{
public:
virtual void Fun1()
{
cout << "Base2::Fun1" << endl;
}
virtual void Fun2()
{
cout << "Base2::Fun2" << endl;
}
virtual void Fun3()
{
cout << "Base2::Fun3" << endl;
}
};
class MultipleDerive :public Base, public Base1, public Base2
{
public:
virtual void MultipleDeriveFun1()
{
cout << "MultipleDerive::Fun1" << endl;
}
virtual void MultipleDeriveFun2()
{
cout << "MultipleDerive::Fun2" << endl;
}
virtual void MultipleDeriveFun3()
{
cout << "MultipleDerive::Fun3" << endl;
}
};
// 多重继承重载
class MultipleDeriveOverride :public Base, public Base1, public Base2
{
public:
virtual void Fun1()
{
cout << "MultipleDerive::Fun1" << endl;
}
virtual void MultipleDeriveFun2()
{
cout << "MultipleDerive::Fun2" << endl;
}
virtual void MultipleDeriveFun3()
{
cout << "MultipleDerive::Fun3" << endl;
}
};
// 公有继承访问父类非公有虚函数
class Base3
{
private:
virtual void Fun1()
{
cout << "Base3::Fun1" << endl;
} }; class Derive1 : public Base3
{ };
typedef void(*Fun)(void);
// 验证虚函数表
void Sub_1();
// 验证无虚函数覆盖的一般继承
void Sub_2();
// 验证虚函数重载父类的虚表
void Sub_3();
// 验证多重继承无重载的虚表
void Sub_4();
// 验证多重继承有重载的虚表
void Sub_5();
// 验证父类指针访问子类自己的虚函数??
void Sub_6();
// 验证公有继承访问父类非公有虚函数
void Sub_7(); int main()
{
//Sub_1();
//Sub_2();
//Sub_3();
//Sub_4();
//Sub_5();
//Sub_6();
Sub_7();
return ;
}
void Sub_7()
{
Derive1 v1;
Fun pFun = (Fun)*((int*)*(int*)(&v1) + );
pFun();
}
void Sub_6()
{
Base *v1 = new Override();
// 多态
v1->Fun1();
Fun pFun = NULL;
//pFun = (Fun)*((Override*)(v1));
pFun();
}
void Sub_5()
{
MultipleDeriveOverride v1;
Fun pFun = NULL;
Base *b = &v1;
Base1 *b1 = &v1;
Base2 *b2 = &v1;
b->Fun1();
b->Fun2();
b->Fun3();
b1->Fun1();
b1->Fun2();
b1->Fun3();
b2->Fun1();
b2->Fun2();
b2->Fun3();
}
void Sub_4()
{
MultipleDerive v1;
Fun pFun = NULL;
int** pVtable = (int**)&v1;
// Base的第一函数
pFun = (Fun)pVtable[][];
pFun();
// Base的第二函数
pFun = (Fun)pVtable[][];
pFun();
// Base的第三函数
pFun = (Fun)pVtable[][];
pFun();
// 继承类的第一函数
pFun = (Fun)pVtable[][];
pFun();
// 继承类的第二函数
pFun = (Fun)pVtable[][];
pFun();
// 继承类的第三函数
pFun = (Fun)pVtable[][];
pFun();
// Base1的第一函数
pFun = (Fun)pVtable[][];
pFun();
// Base1的第二函数
pFun = (Fun)pVtable[][];
pFun();
// Base1的第三函数
pFun = (Fun)pVtable[][];
pFun();
// Base2的第一函数
pFun = (Fun)pVtable[][];
pFun();
// Base2的第二函数
pFun = (Fun)pVtable[][];
pFun();
// Base2的第三函数
pFun = (Fun)pVtable[][];
pFun();
}
void Sub_3()
{
Override v1;
Fun pFun = NULL;
// 运行重载第一函数
pFun = (Fun)*((int*)*(int*)(&v1));
pFun();
// 运行父类第二函数
pFun = (Fun)*((int*)*(int*)(&v1)+);
pFun();
// 运行父类第三函数
pFun = (Fun)*((int*)*(int*)(&v1)+);
pFun();
// 运行重载第二函数
pFun = (Fun)*((int*)*(int*)(&v1) + );
pFun();
// 运行重载第三函数
pFun = (Fun)*((int*)*(int*)(&v1) + );
pFun();
}
void Sub_2()
{
Derive v1;
Fun pFun = NULL;
// 运行父类第一函数
pFun = (Fun)*((int*)*(int*)(&v1));
pFun();
// 运行父类第二函数
pFun = (Fun)*((int*)*(int*)(&v1) + );
pFun();
// 运行父类第三函数
pFun = (Fun)*((int*)*(int*)(&v1) + );
pFun();
// 运行子类第一函数
pFun = (Fun)*((int*)*(int*)(&v1) + );
pFun();
// 运行子类第二函数
pFun = (Fun)*((int*)*(int*)(&v1) + );
pFun();
// 运行子类第三函数
pFun = (Fun)*((int*)*(int*)(&v1) + );
pFun();
}
void Sub_1()
{
Base v1;
Fun pFun = NULL;
cout << "虚函数表地址:" << (int*)(&v1) << endl;
cout << "虚函数表第一函数地址:" << (int*)*(int*)(&v1) << endl;
// 运行第一个函数
pFun = (Fun)*((int*)*(int*)(&v1));
pFun();
// 运行第二个函数
pFun = (Fun)*((int*)*(int*)(&v1) + );
pFun();
// 运行第三个函数
pFun = (Fun)*((int*)*(int*)(&v1) + );
pFun();
// 虚函数表的结束
cout << ((&v1) + ) << endl;
}

C++虚表(V-Table)解析的更多相关文章

  1. 【SQL篇章】【SQL语句梳理 :--基于MySQL5.6】【已梳理:ALTER TABLE解析】

    ALTER TABLE 解析实例: SQL: 1.增加列 2.增加列,调整列顺序 3.增加索引 4.增加约束 5.增加全文索引FULL-TEXT 6.改变列的默认值 7.改变列名字(类型,顺序) 8. ...

  2. HTML网页Table解析

    procedure TForm27.Button1Click(Sender: TObject); var doc2: IHTMLDocument2; doc3: IHTMLDocument3; ita ...

  3. bootstrap table 解析写死的json.并且把进度条放进列中。

    function showPhaseInfo(phase){ //json字符串转json对象 var phaseInfo = eval(phase); $('#phaseTable').bootst ...

  4. Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例

    概要 前一章,我们学习了HashMap.这一章,我们对Hashtable进行学习.我们先对Hashtable有个整体认识,然后再学习它的源码,最后再通过实例来学会使用Hashtable.第1部分 Ha ...

  5. java集合框架之java HashMap代码解析

     java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...

  6. Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  7. 【转】Java HashMap 源码解析(好文章)

    ­ .fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wra ...

  8. JAVA源码剖析(容器篇)HashMap解析(JDK7)

    Map集合: HashMap底层结构示意图: HashMap是一个“链表散列”,其底层是一个数组,数组里面的每一项都是一条单链表. 数组和链表中每一项存的都是一“Entry对象”,该对象内部拥有key ...

  9. java 8 Hashmap深入解析 —— put get 方法源码

    每个java程序员都知道,HashMap是java中最重要的集合类之一,也是找工作面试中非常常见的考点,因为HashMap的实现本身确实蕴含了很多精妙的代码设计. 对于普通的程序员,可能仅仅能说出Ha ...

  10. java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别

    java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别 目录 java基础解析系列(一)---String.StringBuffer.St ...

随机推荐

  1. (中等) HDU 1542 Atlantis,扫描线。

    Problem Description There are several ancient Greek texts that contain descriptions of the fabled is ...

  2. minor gc 和 full gc

    JAVA中关于GC的分析中,需要搞清楚,GC线程在什么时候,对什么东西,做了什么操作. 1-在什么时候 首先需要知道,GC分为minor GC和full GC,JAVA内存分为新生代和老年代,新生代中 ...

  3. Spring学习---JPA学习笔记

    用了一段时间的Spring,到现在也只是处于会用的状态,对于深入一点的东西都不太了解.所以决定开始深入学习Spring. 本文主要记录JPA学习.在学习JPA之前,需要了解一些ORM的概念. ORM概 ...

  4. ASP.NET脚本过滤-防止跨站脚本攻击[转]

    ASP.Net 1.1后引入了对提交表单自动检查是否存在XSS(跨站脚本攻击)的能力.当用户试图用<xxxx>之类的输入影响页面返回结果的时候,ASP.Net的引擎会引发一个HttpReq ...

  5. leetcode day5

    [242]Valid Anagram: Given two strings s and t, write a function to determine if t is an anagram of s ...

  6. ajax 页面请求后,jsp页面定位

    如下图所示.A,B两区域为不动区域,既不随着滚动条的滚动而移动.C区域为异步加载内容区域, 在C区域中,点击查询按钮,需要异步加载查询 结果.但是查询结果会很长,这样子,就需要向下滑动滚动条,用户体验 ...

  7. Core Data需求

    大家都在讨论怎么使用Core Data,但是什么时候用到Core Data,这好像是大家很少讨论的问题 我们使用Core Data ,主要用来存储两种类型的数据:固定的数据,和 可能变化的数据. 1. ...

  8. PHP新手之学习类与对象(3)

    四.访问控制 对属性或方法的访问控制,是通过在前面添加关键字 public.protected 或 private 来实现的.由 public 所定义的类成员可以在任何地方被访问:由 protecte ...

  9. Angular - - ngList、ngRepeat、ngModelOptions

    ngList 在文本输入的分隔的字符串和字符串数组间做转换,可以是一个固定的字符串分隔符(默认逗号)或正则表达式. 格式:ng-list=”value” value:表达式  通过这个值分隔字符串. ...

  10. HTML5 + AJAX ( 原生JavaScript ) 异步多文件上传

    这是在上篇 HTML5 + AJAX ( jQuery版本 ) 文件上传带进度条 的修改版本.后台代码不变就可以接着使用,但是脚本不再使用jQuery了,改为原生的 JavaScript 代码,所以我 ...