C++多态分析(polymorphisn)
前言
借着这次学校的生产实习来回顾下C++的多态,这里讨论下C++的多态以及实现原理。我都是在QT下使用C++的,就直接在QT下进行演示了
多态介绍
面向对象语言中最核心的几个理念就是:封装、继承、多态,其中我感觉多态是真正的核心,第一第二个只是它的辅助。同时多态又是不容易懂的,所以在这就简单的介绍下啦(虽然我也懂得不多,呵呵)
静态联编
第一个简单的小程序(重载的多态)
1 |
#include <QCoreApplication> |
运行结果
说明
VellBibi
类继承了Person
类,VellBibi
里重载了Person
的getAge()
方法,这样就实现了静态的多态,它的实现过程是在编译期间的。这种多态存在硬伤,就是当使用父类指针指向子类对象时,访问的是父类的东西,而不是子类的。这个算是C++的一个特性,在java里面就没有这个情况,因为java直接就是是动态联编,java的多态里面就不存在静态联编
动态联编
第二个简单的小程序(虚函数的多态)
1 |
#include <QCoreApplication> |
运行结果
说明
这个小程序和上一个一样,唯一变得就是在
Person
的getAge()
方法前加了一个virtual
关键字,VellBibi
可加可不加,但最好加上。在C++中virtual
关键字就是用来声明虚函数的,所谓虚函数就是虚的函数嘛,呵呵,就是这个函数不是在编译期间就确定下来了,而是在运行期间动态指定的。这就是导致这个小程序和上个小程序的运行结果不同的原因,当使用父类指针指向子类对象时,调用父类虚函数时系统会自动寻找到子类对象的函数。接下来介绍下C++是怎么实现这个动态指定过程的
多态的实现
第三个小程序(静态联编时对象的大小)
1 |
#include <QCoreApplication> |
运行结果
说明
这个程序只是在第一个程序上加了
sizeof()
,看出来了神马?Person
是4个字节,也就是int age;
的字节数;VellBibi
是8个字节,其实就是Person
的字节数加上VellBibi
的int age;
的字节数。
第四个小程序(动态联编时对象的大小)
1 |
#include <QCoreApplication> |
运行结果
说明
这个程序只是在第二个程序上加了
sizeof()
,这时会发现Person
变8个字节了,为神马呢?这是两个int型的大小啊,why?好了不卖关子了,这是静态Person
的大小加上一个指针的大小,那哪来的指针呢?在Person
里面也没有定义啊!呵呵,这是C++编译器自动加上的,加上用来动态指定的,只要存在virtual
关键字的类最上面都是有一个这样的指针,指向一个vtable
虚拟表,里面记录着这个类所有包含的虚函数地址。
动态联编内存示例图:
第五个小程序(动态联编内存分析)
1 |
#include <QCoreApplication> |
运行结果
说明
将对象第地址强制转换成int型指针来探寻对象内部数据的情况。前两行是对象的头地址的值,很明显这是一个指针;3、4行是第二个值,都是
Person
的int age;
变量; 5行是一个随机值,说明Person
对象里面其实就只有一个int age;
变量而已,其实在C++中类的实现也就是一个C语言的struct而已。再将头地址指向的vtable
里的值取出来看看,7、8行就是各自vtable
的第一个值,可以看出还是一个指针,指向的肯定是代码段相对应的函数啦~这两个指针指向了不同的函数,这也就是动态联编啦~当然还需要一个程序来说明,等会再说;再看看9、10行,都是0,也就是NULL
很好理解,是不是似曾相识啊,没错就是字符串里的结束符啦!
第六个小程序(动态联编的美妙)
1 |
#include <QCoreApplication> |
运行结果
说明
这个应该很好理解了,只是定义了一个
Person
的指针vp
,指向了VellBibi
的对象v
,然后将&v
换成了vp
,其他的都没变;也就是使用父类指针指向子类对象,结果可以看出和第五个程序是一样的,说明了C++的动态联编。
来道分析题
第七个小程序(问题代码)
1 |
#include <QCoreApplication> |
运行结果
问题分析
结果可以看出该打印的
suiShu
变随机数了;我这里使用了点小计俩,我先将对象的头地址当做int看待,然后将VellBibi
对象的头地址赋值给了Person
对象,最后使用Person
对象的指针去调它自己的函数,会发现出错了。上内存分析图吧:
没有改变Person对象头指针
改变了Person对象头指针后
继续分析,
Person
对象的vtable
指针指向了VellBibi
的vtable
,当使用指针去访问时虚函数时就会做动态联编,Person
对象会找到VellBibi
的vtable
然后找到了VellBibi
的getAge()
,而VellBibi
的getAge()
回去调它自己的变量也就是suishu
变量,这下就出问题了,Person
对象哪来的suishu
变量?所以就系统就在那个不是Person
对象内容的地方取了个值,当然这是随机的啦
结束语
写这篇帖子是为了明天实习的每人一讲啦~不过更是一种分享,我是从别人那得到的这份知识,想更好的让更多的人去收获这份知识,这就是分享的意义;当得知我做的努力给别人带来了帮助,我会非常高兴,这就是分享的乐趣。一起分享一起学习,Come on~~~
原文地址: http://vview.ml/2014/07/20/polymorphisn.html
written by Vell Bibi posted at VBlog
C++多态分析(polymorphisn)的更多相关文章
- 深度分析:理解Java中的多态机制,一篇直接帮你掌握!
Java中的多态 1 多态是什么 多态(Polymorphism)按字面的意思就是"多种状态".在面向对象语言中,接口的多种不同的实现方式即为多态.用白话来说,就是多个对象调用同一 ...
- 对Java中多态,封装,继承的认识(重要)
一.Java面向对象编程有三大特性:封装,继承,多态 在了解多态之前我觉得应该先了解一下 ...
- C++三大特性之多态
原文地址:https://qunxinghu.github.io/2016/09/08/C++%20%E4%B8%89%E5%A4%A7%E7%89%B9%E6%80%A7%E4%B9%8B%E5%A ...
- C++多态有哪几种方式?
C++多态方式: (1)静态多态(重载,模板) 是在编译的时候,就确定调用函数的类型. (2)动态多态(覆盖,虚函数实现) 在运行的时候,才确定调用的是哪个函数,动态绑定.运行基类指针指向派生类的对象 ...
- C++ 系列:C++ 对象模型
1 何为C++对象模型 C++对象模型可以概括为以下2部分: 1.语言中直接支持面向对象程序设计的部分: 2.对于各种支持的底层实现机制 语言中直接支持面向对象程序设计的部分,如构造函数.析 ...
- C++对象模型详解
原文链接:吴秦大神的C++对象模型. 何为C++对象模型? C++对象模型可以概括为以下2部分: 1.语言中直接支持面向对象程序设计的部分: 2.对于各种支持的底层实现机制. 语言中直接支持面向对象程 ...
- C++对象模型(虽然在GCC下很大的不同,但是先收藏)
C++对象模型 何为C++对象模型? 部分: 1. 语言中直接支持面向对象程序设计的部分 2. 对于各种支持的底层实现机制 语言中直接支持面向对象程序设计的部分,如构造函数 ...
- C++对象模型6--对象模型对数据访问的影响
如何访问成员? 前面介绍了C++对象模型,下面介绍C++对象模型的对访问成员的影响.其实清楚了C++对象模型,就清楚了成员访问机制.下面分别针对数据成员和函数成员是如何访问到的,给出一个大致介绍. 对 ...
- C++对象模型--C++对象模型
何为C++对象模型? 部分: 1 语言中直接支持面向对象程序设计的部分 2 对于各种支持的底层实现机制 语言中直接支持面向对象程序设计的部分,如构造函数.析构函数.虚函数.继承 ...
随机推荐
- [翻译] - <Entity Framework> - 直接执行数据库命令
原文:[翻译] - <Entity Framework> - 直接执行数据库命令 纯属学习上的记录, 非专业翻译, 如有错误欢迎指正! 原文地址: http://msdn.microsof ...
- NSDictionary 键值对查找
NSDictionary *dic1=[NSDictionary dictionaryWithObjectsAndKeys: @"1",@"a", ...
- 转 Difference between WCF and Web API and WCF REST and Web Service
http://www.dotnet-tricks.com/Tutorial/webapi/JI2X050413-Difference-between-WCF-and-Web-API-and-WCF-R ...
- Shuffle和排序
MapReduce确保每个reducer的输入都按键排序.系统执行排序的过程——将map输出作为输入传给reducer——称为shuffle.shuffle属于不断被优化和改进的代码库的一部分,从许多 ...
- Android 中Activity生命周期分析(二):从AActivity 到BActivity过程分析
如果你没有动手去演示的话,你一定要去动手试试看,这个东西非学容易出错,面试中经常出现,好了,上代码: package com.king.review.base; import android.app. ...
- C++中变量自动初始化的问题
C++中有一些变量在如果没有赋初值会被编译器自动赋值为0,但有的变量又不会这样,而得到一个随机数,下面具体讨论一下: 首先看一下C++中的几个存储区:1.栈区:由编译器自动分配释放 ,存放函数的参数值 ...
- Java 基础之认识 Annotation
Java 基础之认识 Annotation 从 JDK 1.5 版本开始,Java 语言提供了通用的 Annotation 功能,允许开发者定义和使用自己的 Annotation 类型.Annotat ...
- C# 实现对接电信交费易自动缴费
他有这样一个JS PassGuardCtrl.js 部分代码 1 defaults:{ 2 obj:null, 3 random:null,/ ...
- UVa 10253 (组合数 递推) Series-Parallel Networks
<训练之南>上的例题难度真心不小,勉强能看懂解析,其思路实在是意想不到. 题目虽然说得千奇百怪,但最终还是要转化成我们熟悉的东西. 经过书上的神分析,最终将所求变为: 共n个叶子,每个非叶 ...
- RPi 2B Raspbian SD卡内部架构
/***************************************************************************** * RPi 2B Raspbian SD卡 ...