1. 使用继承的虚函数表:

如果不涉及多重继承,每个类只有1个虚函数表,当子类继承父类后,子类可以自己改写和新增虚函数,如下图所示:

子类重写 func_1 后,子函数的 func_1 将会有新的逻辑,不会干扰到父类;

子类新增行的 func_4 方法后,父类无法访问到该方法。

如下代码:

 1 #include <iostream>
2 using namespace std;
3
4 class Father
5 {
6 public:
7 virtual void func_1() { cout << "Father::func_1"; }
8 virtual void func_2() { cout << "Father::func_2"; }
9 virtual void func_3() { cout << "Father::func_3"; }
10 public:
11 int x = 666;
12 int y = 999;
13 };
14
15 class Son : public Father
16 {
17 public:
18 void func_1() { cout << "Son::func_1 "; } //重写了虚函数
19 virtual void func_4() { cout << "Son::func_4 "; } //子类对象新写的虚函数 func_4
20 };
21
22 typedef void(*func_t)(void);
23
24 int main(void)
25 {
26 Father father;
27 cout << "father 对象地址:" << (int*)&father << endl;
28 int* vptr_f = (int*)*(int*)&father; //虚表指针
29
30 for (int i = 0; i < 3; i++) //这里如果想循环4次往下访问,不会访问到子类的 func_4 ,会访问到非法内存
31 {
32 cout << "调用第" << i + 1 << "个虚函数:";
33 ((func_t) * (vptr_f + i))();
34 cout << "地址为:" << *(int*)(vptr_f + i) << endl;
35 }
36
37 cout << "==============================================" << endl;
38
39 Son son;
40 cout << "son 对象地址:" << (int*)&son << endl;
41 int* vptr_s = (int*)*(int*)&son; //虚表指针
42
43 for (int i = 0; i < 4; i++)
44 {
45 cout << "调用第" << i + 1 << "个虚函数:";
46 ((func_t) * (vptr_s + i))();
47 cout << "地址为:" << *(int*)(vptr_s + i) << endl; //打印每个虚函数的地址
48 }
49
50 for (int i = 0; i < 2; i++)
51 {
52 cout << *(int*)((int)&son + 4 + i * 4) << endl;
53 }
54 cout << "sizof(son)==" << sizeof(son) << endl;
55 }

运行结果:

子类的虚函数表生成:

看上图可知,子类对象的 func_1() 地址与父类的 func_1() 地址便可知,重写的虚函数并不是把父类的同名函数覆盖改写,而是在新内存新写。

子类对象是先将父类虚函数表的成员地址全部复制下来,如果子类重写了父类的某个虚函数,便将被重写虚函数的指针,改为新虚函数的指针(指针替换)。

如果子类增加了新的虚函数,那么就会把这个虚函数的地址添加到虚函数表的表尾部。

注意:如果仔细观察我们可以发现,上图中按顺序走的虚函数所存放的地址不同,Father的3个func函数地址不是线性排序。

===========================================================================================================

C++ 虚函数表与多态 —— 继承的虚函数表 & 内存布局的更多相关文章

  1. C++继承 派生类中的内存布局(单继承、多继承、虚拟继承)

    今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化    译 译者前言 一个C ...

  2. C++ 虚函数表与多态 —— 多重继承的虚函数表 & 内存布局

    多重继承的虚函数表会有两个虚表指针,分别指向两个虚函数表,如下代码中的 vptr_s_1.vptr_s_2,Son类继承自 Father 和 Mather 类,并且改写了 Father::func_1 ...

  3. Visual C++ 8.0对象布局的奥秘:虚函数、多继承、虚拟继承(VC直接输出内存布局)

    原文:VC8_Object_Layout_Secret.html 哈哈,从M$ Visual C++ Team的Andy Rich那里又偷学到一招:VC8的隐含编译项/d1reportSingleCl ...

  4. C++对象的内存布局以及虚函数表和虚基表

    C++对象的内存布局以及虚函数表和虚基表 本文为整理文章, 参考: http://blog.csdn.net/haoel/article/details/3081328 http://blog.csd ...

  5. 【整理】C++虚函数及其继承、虚继承类大小

    参考文章: http://blog.chinaunix.net/uid-25132162-id-1564955.html http://blog.csdn.net/haoel/article/deta ...

  6. 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。

    本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...

  7. c++继承中的内存布局

    今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化    译 译者前言 一个C ...

  8. C++各种类继承关系的内存布局

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  9. C++ 各种继承方式的类内存布局

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

随机推荐

  1. Docker学习第三天

    1.配置阿里容器镜像加速器 (1)登录阿里云官网搜索"镜像加速器" (2)添加如上图信息进行配置 (3)重新加载deamon和重启docker服务 sudo systemctl d ...

  2. tp5 生成随机数

    控制器调用 public function GetRanStr(){ if (request()->isPost()) { //生成6位数随机数 return GetRandStr(6); } ...

  3. addslashes()

    addslashes() 函数返回在预定义字符之前添加反斜杠的字符串. 作用:防止sql注入

  4. Java的BigDecimal,对运算封装

    添加maven依赖 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava ...

  5. 关于Java集合框架,这篇讲的还算不错了,建议大家看看!

    集合框架 为什么要用集合而非数组: 虽然数组是保存一组对象最有效的方式,但是数组具有固定尺寸,但在写程序时并不知道将需要多少个对象.而集合能够自动地调整自己的尺寸. 打印数组时,必须使用Arrays. ...

  6. 细说FL Studio中的Wasp合成器功能

    FL Studio 简称FL,因其Logo像水果,故国人亲切的叫他"水果"本章节采用图文结合的方式给大家讲解FL Studio中的Wasp合成器功能.感兴趣的朋友可以一起来交流哦. ...

  7. 怎么用MindManager自带的模板和设计画思维导图

    小编知道大家平时工作学习都很忙,思维导图能完成的效率越高越好.所以今天,小编就为大家介绍两个能高效使用思维导图软件完成制作思维导图的小技巧.保证内容充实美观,还不费时间. 一.使用模板 打开MindM ...

  8. 错误原因:因为desc是mysql里面的关键字

    SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check ...

  9. 自动化运维工具之Puppet基础入门

    一.简介 puppet是什么?它能做什么? puppet是一个IT基础设施自动化运维工具,它能够帮助系统管理员管理基础设施的整个生命周期:比如,安装服务,提供配置文件,启动服务等等一系列操作:基于pu ...

  10. 我与UML相爱相杀的狗血日常

    前言 该怎么说呢,在专业母亲的包办婚姻和我不得不为日后的百万家产[日后的百万年薪,我怕是在做梦]下,我和UML的婚后生活正式开始了.第一天回娘家我亓老师就给出了她最爱的编程作业.说实话,我当初以头发为 ...