虚函数指针和虚函数表

1.虚函数的含义

只有用virtual声明类的成员函数,称之为虚函数。

2.虚函数的作用

就是一句话:实现多态的基石

实现多态的三大步:

1.存在继承关系 子类继承父类

2.子类重写父类的virtual function

3.子类以父类的指针或者是引用的身份出现

3.虚函数的实现原理 多态的实现原理

相信很多人都能说出来其中实现关键原理,就是两点:虚函数表指针(vptr),虚函数表(vftable)

1 虚函数指针在哪? 干什么用的?
2 什么是虚函数表? 表-》信息 虚函数表-》什么信息的? 有什么用?3 A 类  a 对象    b c 成员  a对象内存布局是什么样?
gdb一个普通类 内存布局
一个类里面如果有了虚函数 内存布局?
一个类继承一个类  内存布局是什么样子?
一个类继承并且重写虚函数  内存布局是什么样 虚函数表发生什么变化呢?
  • 普通类

我们首先来看下没有虚函数的情况下 一个普通的类的实例对象在内存中的分布

demo.cpp

#include<iostream>
using namespace std;
class Base{public:Base():m_base(0),m_base1(' '){};void test() const  { cout<<"Base print()"<<endl; }protected:int m_base; char m_base1;
};
int main(){Base b;return 0;
}

在终端输入如下命令

g++ demo.cpp -g
gdb ./a.out
(gdb) list
(gdb) b 14
(gdb) p b
$1 = {m_base = 0, m_base1 = 32 ' '}

可以看到对象b的内存布局是由成员数据构成。

  • 当类中存在虚函数

test.cpp

#include<iostream>
using namespace std;
class Base{
public:Base():m_base(0),m_base1(' '){}virtual void print() const  { cout<<"Base print()"<<endl; }protected:int m_base;  char m_base1;
};
int main(){Base b;return 0;
}

在终端输入如下命令

g++ test.cpp -g
gdb ./a.out

gdb过程如下:

[echoqian@cvm-10_4_1_62 virtual]$ gdb a.out
(gdb) list
4   public:
5       Base():m_base(0),m_base1(' '){}
6       virtual void print() const  { cout<<"Base print()"<<endl; }
7
8   protected:
9       int m_base;
10      char m_base1;
11  };
12  int main(){
13      Base b;
(gdb) b 14
Breakpoint 1 at 0x400904: file test.cpp, line 14.
(gdb) r
(gdb) p b
$1 = {_vptr.Base = 0x400a60 <vtable for Base+16>, m_base = 0, m_base1 = 32 ' '}

此时我们可以看到对象的布局中多了一个虚函数。并且这个虚函数位于这个对象的开头

我们可以打印出虚函数表

(gdb) info vtbl b
vtable for 'Base' @ 0x400a60 (subobject @ 0x7fffffffe420):
[0]: 0x400986 <Base::print() const>

此时虚函数表中有一个函数地址。虚函数表中就存放了这个函数的地址。

  • 子类继承父类不重写虚函数

test.cpp

#include<iostream>
using namespace std;
class Base{
public:Base():m_base(0),m_base1(' '){}virtual void print() const  { cout<<"Base print()"<<endl; }protected:int m_base;  char m_base1;
};class Derive: public Base{private:int m_dirive;
};int main(){Base b;Derive d;return 0;
}

gdb过程如下:

[echoqian@cvm-10_4_1_62 virtual]$ g++ -g test.cpp
[echoqian@cvm-10_4_1_62 virtual]$ gdb test.cpp
(gdb) list
(gdb) b 21
(gdb) r
(gdb) p b
$1 = {_vptr.Base = 0x400b10 <vtable for Base+16>, m_base = 0, m_base1 = 32 ' '}
(gdb) p d
$2 = {<Base> = {_vptr.Base = 0x400af0 <vtable for Derive+16>, m_base = 0, m_base1 = 32 ' '}, m_dirive = 4196928}
(gdb) p &d.m_base
$3 = (int *) 0x7fffffffe408
(gdb) p &d.m_base1
$4 = 0x7fffffffe40c " "
(gdb) p &d.m_dirive
$5 = (int *) 0x7fffffffe410
(gdb) quit
  • 子类继承父类重写虚函数
    test.cpp
#include<iostream>
using namespace std;
class Base{
public:Base():m_base(0),m_base1(' '){}virtual void print() const  { cout<<"Base print()"<<endl; }protected:int m_base;  char m_base1;
};class Derive: public Base{
public: void print() const  { cout<<"Derive print()"<<endl; }};int main(){Base b;Derive d;return 0;
}

gdb过程如下:

[echoqian@cvm-10_4_1_62 virtual]$ g++ -g test1.cpp
[echoqian@cvm-10_4_1_62 virtual]$ gdb ./a.out
(gdb) list
(gdb) b 22
Breakpoint 1 at 0x400960: file test1.cpp, line 22.
(gdb) r
(gdb) p b
$1 = {_vptr.Base = 0x400b40 <vtable for Base+16>, m_base = 0, m_base1 = 32 ' '}
(gdb) p d
$2 = {<Base> = {_vptr.Base = 0x400b20 <vtable for Derive+16>, m_base = 0, m_base1 = 32 ' '}, <No data fields>}
(gdb) info vtbl b
vtable for 'Base' @ 0x400b40 (subobject @ 0x7fffffffe420):
[0]: 0x4009e2 <Base::print() const>
(gdb) info vtbl d
vtable for 'Derive' @ 0x400b20 (subobject @ 0x7fffffffe410):
[0]: 0x400a0c <Derive::print() const>

对比图:

1.虚函数表指针

1.什么是虚函数表指针,他在哪里,有什么用?

我们把对象从首地址开始的4个字节或者是8个字节,这个位置我们称之为虚函数表指针(vptr),它里面包含一个地址指向的就是虚函数表(vftable)的地址。

2.虚函数表

1.什么是虚函数表,他又在哪里,有什么用?

虚函数表说白了就是里面是一组地址的数组(就是函数指针数组),他所在的位置就是虚函数表指针里面所存储的地址,它里面所包含的地址就是我们重写了父类的虚函数的地址(没有重写父类的虚函数那么默认的就是父类的函数地址)。

虚函数指针 虚函数表相关推荐

  1. 【虚函数指针 虚函数表】

    文章目录 虚函数指针和虚函数表 1.虚函数的含义 2.虚函数的作用 3.虚函数的实现原理 多态的实现原理 `普通类` `当类中存在虚函数` `子类继承父类不重写虚函数` 子类继承父类重写虚函数 1.虚 ...

  2. C++多态的原理(虚函数指针和虚函数表)

    C++多态的原理 (虚函数指针和虚函数表) 1.虚函数指针和虚函数表 2.继承中的虚函数表 2.1单继承中的虚函数表 2.2多继承中的虚函数表 3.多态的原理 4.总结 1.虚函数指针和虚函数表 以下 ...

  3. c++ 虚函数多态、纯虚函数、虚函数表指针、虚基类表指针详解

    文章目录 静态多态.动态多态 虚函数 哪些函数类型不可以被定义成虚函数? 虚函数的访问方式 析构函数中的虚函数 虚函数表指针 vptr 多继承下的虚函数表 虚基类表指针 bptr 纯虚函数 抽象类 虚 ...

  4. C++虚函数表、虚函数指针(侯捷)

    C++虚函数表.虚函数指针(侯捷)

  5. C++中虚继承产生的虚基类指针和虚基类表,虚函数产生的虚函数指针和虚函数表

    本博客主要通过查看类的内容的变化,深入探讨有关虚指针和虚表的问题. 一.虚继承产生的虚基类表指针和虚基类表 如下代码:写一个棱形继承,父类Base,子类Son1和Son2虚继承Base,又来一个类Gr ...

  6. 虚函数指针(vptr)与虚函数表(vptb)

    1. 基类指针指向派生类对象 #include "stdafx.h" #include <iostream> using namespace std;class A { ...

  7. c++虚函数和虚函数表

    前言 (1)虚基表与虚函数表是两个完全不同的概念 虚基表用来解决继承的二义性(虚基类可以解决). 虚函数用来实现泛型编程,运行时多态. (2)虚函数是在基类普通函数前加virtual关键字,是实现多态 ...

  8. C++虚函数及虚函数表解析

    一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数. 纯虚函数(Pure Virtual Functi ...

  9. 【C++】虚函数与虚函数表

    1. 虚函数表的结构 #include <iostream> using namespace std;typedef void (*Fun)(void);class Base {publi ...

  10. 虚函数与纯虚函数以及虚函数表之间的关系

    1.虚函数 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.C++中虚函数的作用主要是实现多态机制.所谓多态就是用父类指针指向子类对象,然后通过父类指针调用实际子类的成员函数,这种技术 ...

最新文章

  1. BZOJ.3004.[SDOI2012]吊灯(结论)
  2. opencv将整个图片BGR通道的某个通道进行修改
  3. Less常用语法整理
  4. Python Socket通信黏包问题分析及解决方法
  5. spacy库的安装与使用_为 SpaCy 提供的中文数据模型
  6. python基础--自定义模块、import、from......import......
  7. CNN中全连接层是什么样的
  8. 哪吒的师父太乙真人在神仙界是什么咖位的?
  9. python36安装opencv3.2_Python3.5.3下配置opencv3.2.0的操作方法
  10. 使用python简单分析个人微信好友
  11. ubuntu开机自启动脚本
  12. chrome插件介绍
  13. 【专升本计算机】计算机文化基础练习题(选择题300道附答案)
  14. MXNet之CNN:自定义CNN-OCR算法训练车牌数据集(umpy.ndarray格式数据)实现车牌照片字符识别并评估模型
  15. 纯php实现中秋博饼游戏(2):掷骰子并输出结果
  16. XS9951 两通道多合一同轴高清解码芯片 国产
  17. 利用Matlab实现线性动态电路的可视化研究
  18. 实用的Android ui分析工具
  19. SpringBoot整合Shiro搭建登录注册认证授权权限项目模板
  20. 【物流篇】数商云物流供应链解决方案

热门文章

  1. EDEM颗粒堆积fluent meshing网格生成
  2. 西门子S7系列PLC与触摸屏模拟仿真(无需实物)
  3. 深度卷积神经网络是什么,卷积神经网络结构设计
  4. ae在哪里直接复制合成_AE脚本-合成复制脚本(同合成复制修改相互不影响)True Comp Duplicator v3.9.11+使用教程...
  5. HTTP请求时POST参数到底应该怎么传?
  6. 开源KVM管理工具和平台
  7. 华为转正答辩ppt范文_华为转正答辩ppt模板下载-精选版.ppt
  8. C++ Object Persistence with ODB 学习笔记
  9. 三菱 PLC通讯 MX-Component5.0 官方demo
  10. 盘点那些年我们一起玩过的网络安全工具