C++虚函数表(vtbl)
C++的虚函数的作用就是为了实现多态的机制,利用内存的指针偏移来实现将基类型的指针指向的内存空间用子类对象来初始化。这样经过内部虚表的运作,实现可以通过基类指针来调用子类所定义的方法。
这种技术,其实就是一种泛型技术,试图让不变的代码来实现可变的算法。比如:模板、RTTI、虚函数。实现在编译时决定方法,或者就是在运行时决定方法。
虚函数表:
简称vtbl,这个表中保存了一个类的虚函数地址,这张表解决了继承、覆盖的问题。
在有虚函数的类对象中这个表被分配在对象的内存空间中。创建虚表,赋值地址的工作,其实都是由编译器来完成,编译器通过自动添加代码到构造函数中来实现。
C++的编译器应该保证虚函数表的指针存在于对象实例内存中最前面的位置。既然是首地址,那么当我们获取一个对象的首地址时,其实也就是得到了这个对象所使用的虚表指针的地址,于是也就可以顺利的得到虚表的地址。
class Base
{
public:
virtual void f() {cout << "Base::f()" << endl; };
virtual void g() {cout << "Base::g()" << endl; };
virtual void h() {cout << "Base::h()" << endl; };
};
// 按照上面的类声明,我们来创建一个对象
// 然后得到这个对象所使用的虚表
Base b;
typedef void (*Fun)(void);
Fun pFun = NULL; cout << "虚函数表地址" << (int*)(&b) << endl;
// 其实就是虚指针vbtr的值,因为vbtr的地址和对象的地址相同 cout << "虚函数表: 第一个函数地址" << (int*)*(int*)(&b) << endl; pFun = (Fun)*((int*)*(int*)(&b));
pFun();
运行结果:

然后通过: pFun = (Fun)* ((int*)*(int*)(&b) + 1);取得第二个函数, pFun = (Fun)* ((int*)*(int*)(&b) + 2); 取得第三个函数;
以此类推....
一般继承(无虚函数覆盖):
通过一个子类Derive继承基类,但不做虚函数覆盖,于是子类的虚表如下所示:
class Derive : public Base
{
public:
virtual void f() {cout << "Derive::f()" << endl; };
virtual void g() {cout << "Derive::g()" << endl; };
virtual void h() {cout << "Derive::h()" << endl; };
virtual void f1() {cout << "Derive::f1()" << endl; };
virtual void g1() {cout << "Derive::g1()" << endl; };
virtual void h1() {cout << "Derive::h1()" << endl; };
protected:
private:
};

子类虚函数表:***Base::f()地址***Base::g()地址***Base::h()地址***Derive::f1()地址***Derive::g1()地址***Derive::h1()地址***
作为子类对象,它的虚表和Base类的虚表不是同一个表,子类的虚函数如果不实现,则以此排列。
一般继承(有虚函数覆盖):
class Derive : public Base
{
public:
void f() {cout << "Derive::f()" << endl; };
protected:
private:
};

此时Derive的虚表,第1个函数已经指向了子类的实现。
多重继承(无虚函数覆盖):

每个父类都有自己的虚表,但子类成员函数被放在了第一个声明基类的虚表中。
多重继承(有虚函数覆盖):

三个基类表中的f()位置都被替换成了子类的函数指针
C++虚函数表(vtbl)的更多相关文章
- C++虚函数与虚函数表
多态性可分为两类:静态多态和动态多态.函数重载和运算符重载实现的多态属于静态多态,动态多态性是通过虚函数实现的. 每个含有虚函数的类有一张虚函数表(vtbl),表中每一项是一个虚函数的地址, 也就是说 ...
- [转] C++虚函数与虚函数表
http://www.cnblogs.com/Ripper-Y/archive/2012/05/15/2501930.html http://blog.csdn.net/haoel/article/d ...
- 关于C++中虚函数表存放位置的思考
其实这是我前一段时间思考过的一个问题,是在看<深入探索C++对象模型>这本书的时候我产生的一个疑问,最近在网上又看到类似的帖子,贴出来看看: 我看到了很多有意思的答案,都回答的比较好,下面 ...
- C++迟后联编和虚函数表
先看一个题目: class Base { public: virtual void Show(int x) { cout << "In Base class, int x = & ...
- C++对象内存模型2 (虚函数,虚指针,虚函数表)
从例子入手,考察如下带有虚函数的类的对象内存模型: class A { public: virtual void vfunc1(); virtual void vfunc2(); void func1 ...
- C++对象的内存分布和虚函数表
c++中一个类中无非有四种成员:静态数据成员和非静态数据成员,静态函数和非静态函数. 1.非静态数据成员被放在每一个对象体内作为对象专有的数据成员. 2.静态数据成员被提取出来放在程序的静态数据 ...
- 【C++ Primer | 15】C++虚函数表剖析①
概述 为了实现C++的多态,C++使用了一种动态绑定的技术.这个技术的核心是虚函数表(下文简称虚表).本文介绍虚函数表是如何实现动态绑定的. C++多态实现的原理: • 当类中声明虚函数时,编译器会 ...
- C++虚函数表与虚析构函数
1.静态联编和动态联编联编:将源代码中的函数调用解释为要执行函数代码. 静态联编:编译时能确定唯一函数.在C中,每个函数名都能确定唯一的函数代码.在C++中,因为有函数重载,编译器须根据函数名,参数才 ...
- C++ 类的存储方式以及虚函数表
一.C++成员函数在内存中的存储方式 用类去定义对象时,系统会为每一个对象分配存储空间.如果一个类包括了数据和函数,要分别为数据和函数的代码分配存储空间.按理说,如果用同一个类定义了10个对象,那么就 ...
随机推荐
- KEGG下载某物种最新的版本信息(斑马鱼为例)
步骤一:打开链接并选择物种 http://www.genome.jp/kegg-bin/get_htext?hsa00001+3101 步骤二:对文件进行解析 步骤三:统计信息 一级结构(6大类): ...
- sql:查询课程号'0312091006'成绩排名第5到第10之间的学生学号
select top 6 sno from (select top 10 sno,mark from student_Coursewhere ccno='0312091006' order by ma ...
- python使用外部PY文件的变量
在用python和selenium编写登录等脚本时,一直都是给用户名和密码直接赋值.但是考虑到这样不便于管理,而且可能多个地方用到同一个变量,所以想把变量放在一个单独的文件中进行管理. 以登录脚本为例 ...
- Django的cookie学习
为什么要有cookie,因为http是无状态的,每次请求都是独立的,但是我们还需要保持状态,所以就有了cookie cookie就是保存在客户端浏览器上的键值对,别人可以利用他来做登陆 rep = r ...
- python之信号量【Semaphore】
# 互斥锁同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据,比如 # 一个厕所有3个坑,那么最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去 import ...
- 面向对象设计模式纵横谈:Factory Method 工厂方法模式(笔记记录)
从耦合关系谈起 耦合关系直接决定着软件面对变化时的行为 -模块与模块之间的紧耦合使得软件面对变化时,相关模块都要随之更改 -模块与模块之间的松耦合使得软件面对变化时,一些模块更容易被替换或者更改,但其 ...
- PAT 1083 是否存在相等的差(20)(代码+思路)
1083 是否存在相等的差(20 分) 给定 N 张卡片,正面分别写上 1.2.--.N,然后全部翻面,洗牌,在背面分别写上 1.2.--.N.将每张牌的正反两面数字相减(大减小),得到 N 个非负差 ...
- python使用input()来接受字符串时一直报错“xxx is not defined”
报错信息: “Please input your guess: gussTraceback (most recent call last): File "coinGuessGame.py& ...
- 在Jmeter中用JAVA获取Rolling Date
Rolling Date_Weekly import java.util.*; import java.text.SimpleDateFormat; import java.text.DateForm ...
- urlrewritefilter 本地windowsxp 上正常 使用 ,但是 到linux服务器 上 则时好时坏 ,不起作用
可能原因: tuckey.org 无法正常访问 ,urlrewrite 配置 网络 dtd 无法下载 .. 先把 urlrewrite 日志 配置好: <filter> <filte ...