文章目录

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

虚函数指针和虚函数表

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. C++多态的原理(虚函数指针和虚函数表)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test (default-test)
  2. android如何删除项目,AndroidStudio中怎样删除项目
  3. Java 蓝桥杯 龟兔赛跑预测
  4. 阿里云宣布与国内规模最大的汽车企业上汽集团合作
  5. jquery对标签属性操作
  6. python 多分类情感词典_基于情感词典的python情感分析
  7. 丑数java_丑数-Java研发军团
  8. 自由职业接单,大平台,有保障
  9. ionic框架中TABS中tabs-striped条形切换问题
  10. 关于JavaScript的Object所有方法
  11. 【优秀易用的无损音乐播放器】Amarra Luxe for Mac 4.3
  12. TPC-C和TPC-H
  13. 国外数据平台统计分析sdk
  14. Romberg(龙贝格)积分法 | matlab
  15. 如何激励公司员工最有效?
  16. 台式计算机usb口接触不良,台式机usb接口不好怎么办
  17. 浅谈Servlet与JSP
  18. java 只初始化一次_java – 仅对多个测试类执行一次初始化代码
  19. 2023Facebook该如何养号?Facebook防封指南了解一下!
  20. 快速突破流量瓶颈的方法,需从如下五点数据分析

热门文章

  1. 国内有哪些比较靠谱的云主机供应商,性价比高一点的?
  2. 服务器raid卡安装在什么位置,安装raid卡
  3. 注意: yyyy-MM-dd 与 YYYY-MM-dd
  4. 卷积神经网络与全连接神经网络
  5. Win7 注册ocx控件 “DllRegisterServer的调用失败,错误代码为0x80040200 ”
  6. 访问Servlet的几种方式
  7. CTF密码学——初探
  8. 神经网络预测股价python talib_用机器学习来预测股价(代码+文档)——2018年iNTUtion决赛大作!...
  9. 对接阿里云短信服务(附视频教程)
  10. python3如何下载模块