前言

虚函数执行速度要稍慢一些。为了实现多态性,每一个派生类中均要保存相应虚函数的入口地址表,函数的调用机制也是间接实现。所以多态性总是要付出一定代价,但通用性是一个更高的目标。

实验环境

Windows10 企业版

Visual Studio2017 15.8.1

引入虚函数后内存大小变

没有虚函数时类占用内存大小

#include<iostream>
using namespace std; class Base
{
public:
Base()
{
cout << "Create Base" << endl;
}
~Base()
{
cout << "Free Base" << endl;
}
public:
void Show()
{
cout << "This is Base Show()" << endl;
}
private:
int x;
}; void main()
{
cout << sizeof(Base) << endl;
Base b;
}

占用内存为4字节。在x86 模式下,整形变量大小为4字节

有虚函数时类占用内存大小

#include<iostream>
using namespace std; class Base
{
public:
Base()
{
cout << "Create Base" << endl;
}
~Base()
{
cout << "Free Base" << endl;
}
public:
virtual void Show()
{
cout << "This is Base Show()" << endl;
}
private:
int x;
}; void main()
{
cout << sizeof(Base) << endl;
Base b;
}

占用内存为8字节。在x86 模式下,整形变量大小为4字节。剩下4字节是虚函数表指针,指针变量在x86下占内存大小4字节。

代码中只定义了一个虚函数,定义多个虚函数,类的大小还是8。虚函数表的指针指向的是虚函数表的入口地址

虚函数表

 #include<iostream>
using namespace std; class Base
{
public:
Base()
{
cout << "Create Base" << endl;
}
~Base()
{
cout << "Free Base" << endl;
}
public:
virtual void Show()
{
cout << "This is Base Show()" << endl;
}
virtual void Print()
{
cout << "This is Base Print()" << endl;
}
void Fun()
{
cout << "This is Base Fun()" << endl;
}
private:
int x;
}; class D :public Base
{
public:
D()
{}
~D()
{}
public:
void Show()
{
cout << "This is D Show()" << endl;
}
void Fun()
{
cout << "This is D Fun()" << endl;
}
virtual void List()
{
cout << "This is D List()" << endl;
}
private:
int y;
}; void main()
{
D d;
}

虚函数表前后变化

虚函数表在构造父类的时候会记录所有父类的虚函数

这里面少显示了子类的List虚方法,少显示是编译器的问题。但是你不能通过父类指针访问子类List()方法,因为List超出了父类范围。

子类构造完成后,子类重写了父类的虚函数,虚函数表中的虚函。数就变成了子类的。狸猫混太子,偷梁换柱的意思

C++——多态实现原理分析的更多相关文章

  1. c/c++ 多态的实现原理分析

    多态的实现原理分析 当类里有一个函数被声明成虚函数后,创建这个类的对象的时候,就会自动加入一个__vfptr的指针, __vfptr维护虚函数列表.如果有三个虚函数,则__vfptr指向的是第一个虚函 ...

  2. 【C#多态】as 类型检测(原理分析) ---用于多态检

    as(OpCodes.Castclass)功能:测试对象引用(O 类型)是否为特定类的实例.相当于:expression is type ? (type)expression : (type)null ...

  3. AIDL原理分析

    季春初始,天气返暖,新冠渐去,正值学习好时机.在Android系统中,AIDL一直在Framework和应用层上扮演着很重要的角色,今日且将其原理简单分析.(文2020.03.30) 一.开篇介绍 1 ...

  4. Handler系列之原理分析

    上一节我们讲解了Handler的基本使用方法,也是平时大家用到的最多的使用方式.那么本节让我们来学习一下Handler的工作原理吧!!! 我们知道Android中我们只能在ui线程(主线程)更新ui信 ...

  5. Java NIO使用及原理分析(1-4)(转)

    转载的原文章也找不到!从以下博客中找到http://blog.csdn.net/wuxianglong/article/details/6604817 转载自:李会军•宁静致远 最近由于工作关系要做一 ...

  6. 原子类java.util.concurrent.atomic.*原理分析

    原子类java.util.concurrent.atomic.*原理分析 在并发编程下,原子操作类的应用可以说是无处不在的.为解决线程安全的读写提供了很大的便利. 原子类保证原子的两个关键的点就是:可 ...

  7. Android中Input型输入设备驱动原理分析(一)

    转自:http://blog.csdn.net/eilianlau/article/details/6969361 话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反 ...

  8. 转载:AbstractQueuedSynchronizer的介绍和原理分析

    简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过 ...

  9. Camel运行原理分析

    Camel运行原理分析 以一个简单的例子说明一下camel的运行原理,例子本身很简单,目的就是将一个目录下的文件搬运到另一个文件夹,处理器只是将文件(限于文本文件)的内容打印到控制台,首先代码如下: ...

随机推荐

  1. Python第一阶段06

    1.面向对象编程: class Dog: def __init__(self, name): self.name = name def bulk(self): print("%s 汪汪汪.. ...

  2. MySQL5.7.10 初始化失败error

    http://blog.csdn.net/saife/article/details/51133317

  3. Python 的包管理工具 distribute, setuptools, easy_install命令与 pip命令

    Setuptools 是 Python Enterprise Application Kit (PEAK)的一个副项目,它是 Python 的disutils工具的增强工具,可以让程序员更方便地创建和 ...

  4. 系统调用system call以及strace/dtruss

    计算机系统的各种硬件资源是有限的,在现代多任务操作系统上同时运行的多个进程都需要访问这些资源,进程是不允许直接操作这些资源的,所有对这些资源的访问都必须有操作系统控制.也就是说操作系统是使用这些资源的 ...

  5. 对String对象进行JSON序列化

    对对象进行JSON序列化,会得到类似key:value的形式. 但是如果对一个String字符串进行JSON序列化会得到什么? 测试下: public class TestMain2 {     pu ...

  6. Linux 下 安装 Jmeter

    Linux下安装jmeter 1.1 下载JMeter 官方网站下载最新版本: http://jmeter.apache.org/download_jmeter.cgi    两个只是解压方式不一样而 ...

  7. 漏洞复现之JBoss 4.x JBossMQ JMS 反序列化漏洞(CVE-2017-7504)

    前言: 序列化就是把对象转换成字节流,便于保存在内存.文件.数据库中:反序列化即逆过程,由字节流还原成对象. Java中的ObjectOutputStream类的writeObject()方法可以实现 ...

  8. java学习笔记(7)--链表

    标签(空格分隔):笔记 java其实已经将很多底层的数据结构进行了封装,虽然工作用不到,但是笔试和面试问的还是比较频繁的,而且这种面试题还是直接手撕代码,故专门总结一下. 1. 概念 1.1 链表(L ...

  9. 使用静态方法CreateInstance()创建数组

    Array类是一个抽象类,所以不能使用构造函数来创建数组.但除了可以使用C#语法创建数组的实例之外,还可以使用静态方法CreateInstance()创建数组. 如果事先不知道元素的类型,该静态方法就 ...

  10. TCP/IP学习笔记9--以太网之基本概念1: 分类,连接方式

    时间是变化的财富.时钟模仿它,却只有变化而无财富. -- 泰戈尔 以太网(Ethernet)一词源于Ether(以太), 是介质的意思.在爱因斯坦哥们提出量子力学之前,人们普遍认为宇宙空间充满以太,并 ...