C++对象内存模型2 (虚函数,虚指针,虚函数表)(转)
class A {
public:
virtual void vfunc1();
virtual void vfunc2();
void func1();
void func2();
virtual ~A();
private:
int m_data1, m_data2;
};
class B : A {
public:
virtual void vfunc1();;
void func2();
virtual ~B();
private:
int m_data3;
};
class C : B {
public:
virtual void vfunc1();
void func();
private:
int m_data1, m_data4;
};
注:在子类中出现与父类相同名称的变量和非虚函数不是最佳实践,这里是为了说明其内存结构。

对其分析如下:
1. 每个含有虚函数的类在内存中多一根指针(vptr),见图中a,b,c对象中第一个位置,存储的是虚函数表(vtbl)所在的位置。
2. 虚函数表(vtbl)存储着所有虚函数的位置(地址),由于其动态绑定特性,在覆写(override)后在子类中存储的虚函数位置与父类中不相同。
3. 分析上述代码, B继承A,所以A中的数据部分也被B继承下来,同时B添加上了自己的数据部分m_data3,加之vptr,组成了B左侧的内存布局。
A中的虚函数vfunc1(),vfunc2()可以被覆写和动态绑定。
所以在B中,vfunc1()被覆写,其vtbl中对应项指向了新的函数的位置(亮蓝色)。vfunc2()未被覆写,仍然指向原先位置(深蓝色)。
C与B同理,vfunc1()被覆写,其vtbl中对应项指向了新的函数的位置(橘黄色)。vfunc2()未被覆写,仍然指向原先位置(深蓝色)。
非虚函数静态绑定,存储在单独的内存空间(code memory section,灰色函数部分),调用时把对象的this指针,传给一个invisible参数,以便确定谁在调用函数。
4. 调用虚函数的语句的C语言形式如图中下部分所示,其中n表示对应的函数在第几个位置(编译器在建立虚函数表的时候已知),从而实现动态绑定。
C++对象内存模型2 (虚函数,虚指针,虚函数表)(转)的更多相关文章
- C++对象内存模型2 (虚函数,虚指针,虚函数表)
从例子入手,考察如下带有虚函数的类的对象内存模型: class A { public: virtual void vfunc1(); virtual void vfunc2(); void func1 ...
- 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响
首先重新回顾一下关于类/对象大小的计算原则: 类大小计算遵循结构体对齐原则 第一个数据成员放在offset为0的位置 其它成员对齐至min(sizeof(member),#pragma pack(n) ...
- 对C++对象内存模型造成的影响(类/对象的大小)
首先重新回顾一下关于类/对象大小的计算原则: 类大小计算遵循结构体对齐原则 第一个数据成员放在offset为0的位置 其它成员对齐至min(sizeof(member),#pragma pack(n) ...
- c++ 虚函数和纯虚函数
在你设计一个基类的时候,如果发现一个函数需要在派生类里有不同的表现,那么它就应该是虚的.从设计的角度讲,出现在基类中的虚函数是接口,出现在派生类中的虚函数是接口的具体实现.通过这样的方法,就可以将对象 ...
- C++ - 虚基类、虚函数与纯虚函数
虚基类 在说明其作用前先看一段代码 class A{public: int iValue;}; class B:public A{public: void bPrintf(){ ...
- c++中虚函数和纯虚函数定义
只有用virtual声明类的成员函数,使之成为虚函数,不能将类外的普通函数声明为虚函数.因为虚函数的作用是允许在派生类中对基类的虚函数重新定义.所以虚函数只能用于类的继承层次结构中. 一个成员函数被声 ...
- C++ 虚函数 、纯虚函数、接口的实用方法和意义
也许之前我很少写代码,更很少写面向对象的代码,即使有写多半也很容易写回到面向过程的老路上去.在写面向过程的代码的时候,根本不管什么函数重载和覆盖,想到要什么功能就变得法子的换个函数名字,心里想想:反正 ...
- C++多态、虚函数、纯虚函数、抽象类、虚基类
一.C++多态 C++的多态包括静态多态和动态多态.静态多态包括函数重载和泛型编程,动态多态包括虚函数.静态多态是指在编译期间就可以确定,动态多态是指在程序运行时才能确定. 二.虚函数 1.虚函数为类 ...
- 【转】C++ 虚函数&纯虚函数&抽象类&接口&虚基类
1. 动态多态 在面向对象语言中,接口的多种不同实现方式即为多态.多态是指,用父类的指针指向子类的实例(对象),然后通过父类的指针调用实际子类的成员函数. 多态性就是允许将子类类型的指针赋值给父类类型 ...
- C++(九)— 虚函数、纯虚函数、虚析构函数
1.虚函数 原因:通过指针调用成员函数时,只能访问到基类的同名成员函数.在同名覆盖现象中,通过某个类的对象(指针及引用)调用同名函数,编译器会将该调用静态联编到该类的同名函数,也就是说,通过基类对象指 ...
随机推荐
- 一文带你了解 Flink 的基本组件栈
作为实时计算领域的佼佼者,Flink 的基本组件同样值得我们仔细研究. Flink 同样遵循着分层的架构设计理念,在降低系统耦合的同时,也为上层用户构建 Flink 应用提供了丰富且友好的接口. Fl ...
- Disable foreign key checks during import
The command SET FOREIGN_KEY_CHECKS=0; sets the value of a variable in a session scope. So it affects ...
- Sitecore 6.4 升级Sitecore 8.2.7准备
考虑Sitecore升级?尽管这可能是一项令人生畏的任务,但这三个技巧可以帮助您无缝地完成整个过程. 如果您当前正在运行较旧版本的Sitecore并希望升级到最新版本,那么您可能已经瞥了一眼说明,但却 ...
- golang知识精要(一)
一.第一章 命令行参数可通过os.Args访问,os.Args是切片 切片遵循左闭右开原则,如sl[1:3]不包含下标为3的元素 for循环两种方式 方式一: for initial; conditi ...
- 11. Scala数据结构(下)-集合操作
11.1 集合元素的映射-map映射操作 11.1.1 看一个实际需求 要求:请将List(3,5,8)中所有的元素都*2,将其结果放到一个新的集合中返回,即返回一个新的List(6,10,16),请 ...
- sqlalchemy 配合bootstrap-table实现后台分页
创建公共的mysql连接函数 def db_session(): db_config='mysql+mysqldb://'+ mysqluser + ':' + mysqlpassword+'@'+m ...
- Linux学习笔记之LVM基本应用,扩展及缩减实现
0x00 LVM概述 LVM是逻辑盘卷管理(Logical Volume Manager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和分区之上的一个逻辑层,来提高磁盘 ...
- [個人紀錄] windows form , usercontrol design 模式不見
windows form 跟 usercontrol 都變成cs檔 無法點擊進入設計模式 <Compile Include="Form1.cs"/> <Compi ...
- 简单聊聊服务发现(redis, zk,etcd, consul)
什么是服务发现? 服务发现并没有怎样的高深莫测,它的原理再简单不过.只是市面上太多文章将服务发现的难度妖魔化,读者被绕的云里雾里,顿觉自己智商低下不敢高攀. 服务提供者是什么,简单点说就是一个HTTP ...
- Android 权限的一些细节
Android 权限的一些细节 1 哪些app属于system app?为了区分privilege app和system app,这里先说明system app是什么,避免之后的讨论概念混乱. 在Pa ...