C++虚表(V-Table)解析
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)解析的更多相关文章
- 【SQL篇章】【SQL语句梳理 :--基于MySQL5.6】【已梳理:ALTER TABLE解析】
		
ALTER TABLE 解析实例: SQL: 1.增加列 2.增加列,调整列顺序 3.增加索引 4.增加约束 5.增加全文索引FULL-TEXT 6.改变列的默认值 7.改变列名字(类型,顺序) 8. ...
 - HTML网页Table解析
		
procedure TForm27.Button1Click(Sender: TObject); var doc2: IHTMLDocument2; doc3: IHTMLDocument3; ita ...
 - bootstrap table 解析写死的json.并且把进度条放进列中。
		
function showPhaseInfo(phase){ //json字符串转json对象 var phaseInfo = eval(phase); $('#phaseTable').bootst ...
 - Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例
		
概要 前一章,我们学习了HashMap.这一章,我们对Hashtable进行学习.我们先对Hashtable有个整体认识,然后再学习它的源码,最后再通过实例来学会使用Hashtable.第1部分 Ha ...
 - java集合框架之java HashMap代码解析
		
java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...
 - Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例
		
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
 - 【转】Java HashMap 源码解析(好文章)
		
 .fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wra ...
 - JAVA源码剖析(容器篇)HashMap解析(JDK7)
		
Map集合: HashMap底层结构示意图: HashMap是一个“链表散列”,其底层是一个数组,数组里面的每一项都是一条单链表. 数组和链表中每一项存的都是一“Entry对象”,该对象内部拥有key ...
 - java 8 Hashmap深入解析 —— put get 方法源码
		
每个java程序员都知道,HashMap是java中最重要的集合类之一,也是找工作面试中非常常见的考点,因为HashMap的实现本身确实蕴含了很多精妙的代码设计. 对于普通的程序员,可能仅仅能说出Ha ...
 - java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别
		
java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别 目录 java基础解析系列(一)---String.StringBuffer.St ...
 
随机推荐
- Cdoefroces #354
			
A题 题意:给定一些数,然后求一次交换以后最大的数和最小的数之间的最大距离 分析:找到最大数和最小数的位置,然后判断是把位置大的移到最后还是把位置小的移到开始位置即可 #include <ios ...
 - [cocos2d-x] --- CCNode类详解
			
Email : awodefeng@163.com 1 CCNode是cocos2d-x中一个很重要的类,CCNode是场景.层.菜单.精灵等的父类.而我们在使用cocos2d-x时,接触最多的就是场 ...
 - 在GitHub上创建上传下载开源项目代码
			
1.注册GitHub帐号,创建GitHub项目代码仓库 1.1.注册GitHub帐号 在使GitHub之前,需要先登录其官网注册一个免费使用的账号.登录 https://github.com/join ...
 - sysctl.conf和limit.conf备忘待查
			
#################################limits.conf设置################################### #修改最大进程和最大文件打开数限制v ...
 - python模块的打包setuptools
			
样例代码:新建test.py文件,内容如下: print "show me" 新建一个setup.py编译文件,内容如下: from distutils.core import s ...
 - Centos下wget下载整个网站,或者目录全部文件
			
需要下载某个目录下面的所有文件.命令如下 wget -c -r -np -k -L -p www.xxx.org/pub/path/ 在下载时.有用到外部域名的图片或连接.如果需要同时下载就要用-H参 ...
 - iOS 之 后台下载,前台显示模式,双 block
			
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //耗时的操作 NSURL *url ...
 - 2.10. 代码片段:demo方法(Core Data 应用程序实践指南)
			
该代码段我觉得没有太多东西 - (void)applicationDidBecomeActive:(UIApplication *)application { [self cdh]; [self de ...
 - Delphi获取其它进程窗口句柄的3种方法
			
本文主要跟大家介绍Delphi中获取其它进程的窗口句柄,在Delphi中获取其它进程的窗口句柄,绝大部分人首先想到的会使用:FindWindow或者用GetWindow来遍历查找,如: handle ...
 - because of many connection errors; unblock with 'mysqladmin flush-hosts
			
环境:linux,mysql5.5.37 错误:Host is blocked because of many connection errors; unblock with 'mysqladmin ...