深度搜索C++对象模型 - 函数语义学

深度探索C++对象模型(清晰版.新).rar 立即下载


深度搜索C++对象模型:  Function Semantics

C++支持三种类型的 member function: static nonstatic virtual; 后文分析他们的差异

//*********************************************************************************************//
---> "nonstatic member function: ( 非静态成员函数 )":
C++设计准则之一就是: 非静态成员函数至少要和非成员函数有相同的效率;
那么
Func( const A *this );
A.Func();
他们至少要具有相同的效率, 也就是说 选择非静态成员函数不该带来额外的负担;
事实上 编译器在内部已经"将 member function 转换为 nonmember function";
改写规则:
-> 改写函数的函数原型, 安插一个额外的函数参数, this 指针.. 提供一个存取管道
-> 将每一个对非静态数据成员的操作改为"经由 this 指针来存取";
-> 将成员函数重新改写为一个外部函数,并且经过"函数改名" ( 支持多态 进行独一无二的改名 );

//-----------------------------------------------------------------------------------------------------------------------//
---> "virtual member function: ( 虚拟成员函数 )":
class A
{
 public:
  virtual void Func1();
};

A *ptr;
ptr->Func1();
这个调用在内部将被转化为: ( * ptr->vptr[0] ) ( ptr );
-> vptr表示由编译器产生的指针, 指向 vtbl, 他被安插到每一个"声明有 virtual functions"的 class object 中;
-> 0 是 virtual table slot 的索引值, 关联到 Func1(); 函数
-> 第二个 ptr 是 this 指针

//-----------------------------------------------------------------------------------------------------------------------//
---> "static member function: ( 静态成员函数 )":
如果一个class里存在 static member function, 那么他将会被转化为一般的 nonmember function 调用;
-> 一个 static member function 不能直接存取其 class 中的 nonstatic member;
-> 他不能被声明为 const volatile virtual;
-> 他不需要经由 class object 才被调用;

//*********************************************************************************************//

---> "virtual member function: ( 虚拟成员函数 )":
为了支持 virtual function 机制, 首先必须能够对于多态对象有某种形式的"执行期类型判断法",
在C++中 多态表示"以一个 public base class 的指针, 寻址出一个 derived class object"的意思;
Point *ptr;
ptr = new Point2d;
ptr的多态机能主要扮演一个 "输送机制" 的角色, 经由他,我们可以在程序的任何地方采用一组 public derived 类型, 这种多态形式"是消极的";
当被指出的对象真正被使用的时候, 多态就变成"积极"的了, 如:
ptr->Func();

欲判断哪些 class 展现出多态特性 我们需要一些额外的执行期信息 ( 光凭是 class 和 struct 并不能很好的判断 )
因此识别一个 class 是否支持多态, "唯一适当"的方法就是看他是否有任何 virtual function, 那么他需要这一份额外的信息;

什么样的额外信息能让我们在执行期调用正确的 Func(); ? 我们需要知道:
-> ptr所指向的真实类型, 这可以使我们选择正确的 Func() 实例
-> Func() 实例的位置, 以便我们能够调用他;

实际上就是 vptr 和 vtbl,
为了找到 vtbl , class object 被安插了一个 vptr 指向 vtbl;
为了找到函数地址, vtbl 里每一个表格地址里都是一个函数地址;

一个 class 只会有一个 vtbl, 每一个 vtbl 中内含与之对应的 class object 中的所有 active virtual function 地址 包括
-> 这一 class override 的所有函数实例;
-> 继承自 base class  的 virtual 函数实例;
-> 虚函数实例;

class A
{
 public:
 virtual void Func1() { };
};

class B : public A
{
 public:
 virtual void Func1() { };
 virtual void Func2() { };
};

当 class B 继承自 class A 时 发生了什么:
-> 他可以继承来自 base class 的 virtual function 实例 并且拷贝到 vtbl 相对应的 slot 中内
-> 他要把自己的函数实例 override 到 vtbl 中, 替代 base class 的 slot
-> 他可以加入新的 virtual function, 此时 vtbl 的尺寸会变大

A a;
B b;
对于实例a 他有一个 vtbl 内含了 Func1(); ( 此Func1() 为 A::Func1() );
对于实例b 他有一个 vtbl 内含了 Func1(); ( 此Func1() 为 B::Func1() ); Func2();

//*********************************************************************************************//

我们怎么使用我们上文加入的额外信息来判断我们需要哪个 virtual function 的调用?
--> "单继承":
A *ptr;
ptr = new B;
ptr->Func1();
-> 一般来说 每次调用 Func1(); 时,  我们并不知道 ptr 所指向的 class object 的真实类型, 但是我们知道, 经由 ptr 可以存取到这个对象的 vtbl;
-> 我们也不知道哪一个 Func1(); 实例被调用, 但是我们知道每一个 Func1(); 函数地址都被放在了 slot 1 中;

此时: ptr = new B;  ptr 指向了 class B object,  通过 A 内存模型解释 class B object 时;
我们找到了 vptr, 找到了 vtbl, 在找到 slot 1, 这样就可以调用正确的 Func1(); 了, 我们并不需要知道 slot 1 里面到底是什么内容
( 很明显vptr指向了 class B vtbl, 自然调用的是 class B 的 virtual Func1() )

--> "多重继承":
class A
{
 public:
 virtual void Func1() { };
};

class B
{
 public:
 virtual void Func2() { };
};

class C : public A, public B
{
    public:
    virtual void Func1() { };
    virtual void Func2() { };
    virtual void Func3() { };
};

A *a = new C;  // 不会调整 因为 class A 是第一 base class;
B *b = new C;  // 需要经过调整 因为 class B 不是第一 base class; ( 加上了 sizeof( A ); )
此时 class C object 之中 会有两根 vptr,
--> "base A vptr" 其中第一根按照我们上文单继承所说 他内含了 base class A 的所有 virtual function, 并且 override 了所有已经重写的 function,
而且 他还在这里"加入了新写的的 virtual function", ( 即这张表里有 "C::Func1(); C::Func3();" )
--> "base B vptr" 第二根只会进行上面的前两个步骤, 就是 内含 base class B 的所有 virtual function, 并且 override 了所有已经重写的 function,
( 这张表里有 "C::Func2();" )
C c;
A *a_1 = new C;         // 不需要调整 直接按照 A 的内存模型解释C, 但是只可以解释到 C::Func1()
A a_2 = c;                  // 经过拷贝构造函数, vptr 指向了 A 的 vtbl,  解释到 A::Func1();
B *b_1 = new C;         // 需要调整, 调整之后按照 B 的内存模型解释, 只可以解释到 C::Func2()
B b_2 = c;                  // 经过拷贝构造函数, 而且调整了 vptr, 指向了 B 的 vtbl, 解释到 B::Func2();

--> "虚拟继承":
class A
{
 public:
    virtual void Func1() { };
};

class B : virtual public A
{
 public:
    virtual void Func1() { };
    virtual void Func2() { };
};

对于 class B object 来说 他有一根由 "virtual function 机制带来的 vptr_1", 还有一根由 "virtual base class 机制带来的 vptr_2";
而虚拟继承时, vptr_1 指向的 vtbl 内部只含有自己的虚函数, 也就是 B::Func2(); 而另一个 override 的虚函数 在 vptr_2 指向的 vtbl 里;
所以虚拟继承时, 两者之间的转换必须调整指针, 而且非常复杂...   所以"不要在一个 virtual base class 中声明 非静态变量... 否则可能会越来越复杂";

//*********************************************************************************************//

---> "函数的效能":
对于函数 一般有几种形式:
-> inline member;
-> nonmember friend;
-> static member;
-> virtual member ( 单继承 )
-> virtual member ( 多继承 )
-> virtual member ( 虚拟继承 )
经过实验发现: 前三种具有完全相同的效率 ( 实际上他们被编译器改编成了完全相同的形式 ), 越往后 效率越低;

//*********************************************************************************************//

CCF CSP历年题解(python) 菜鸡一枚,没参加过算法竞赛,单纯为了抵研究生考试复试才刷题,通过写博客记录下来,希望能和大家互相交流,代码质量不高,大家见谅。 因为考研等原因,题目不定期更新… 第一题 201312-1出现最多次数的数 ... 阅读详情

相关推荐

Hi3516CV610开发板实战:从零搭建智能视觉监控系统

本文详细介绍了从零开始基于Hi3516CV610开发板搭建智能视觉监控系统的完整实战流程。涵盖硬件连接、系统配置、摄像头集成、网络设置、固件烧录到视频处理与智能分析功能开发,提供了丰富的实践经验和调试技巧,帮助开发者快速掌握嵌入式视觉系统开发。

vvv99的博客 562

深度探索C++对象模型

c++对象模型语言中直接支持面向对象程序设计的部分对于各种支持的底层实现机制说白了是介绍编译器是如何支持、实现C++的面向对象机制的。如,继承、虚函数、指向class members的指针等等,编译器是如何实现的。本书C++语法基于C++95本书出版自2001年,虽然书中用到的标准早已盖棺定论,cfront编译器也早已过时,当时来看一些无法确定的标准、难以实现的技术、功能也早已实现,但是对C++对象模型的某些实现方式依然沿用至今。这本书依然不过时。

surfaceyan的博客 1825

一文详解脉搏血氧测量原理与方法

本文摘要:血氧饱和度(SpO2)是评估人体氧合功能的重要指标,反映血红蛋白携氧能力。其测量基于光电容积描记法(PPG),利用红光(660nm)和红外光(940nm)通过组织时的吸收差异计算。脉搏波特征与心血管状态相关,动脉硬化会影响波形特征。Masimo公司的信号提取技术(SET)通过并行算法有效解决了传统血氧仪在运动、弱灌注情况下的测量误差问题,显著提升了临床监测的准确性和可靠性。该技术已成为血氧监测的金标准,在降低误报率、缩短响应时间方面具有显著优势。

m0_50146396的博客 2015

C++对象模型

今天阅读了《深度探索C++对象模型》的C++对象模型的章节1.1~1.5章节的内容。并结合《Primer C++第五版》中第六章函数的内容,逐步理解了vtbl和vptr的概念。 vptr(virtual pointer) 每一个class object中都会包含一个vptr,用于指向vtbl,保存在每一个类对象存储空间的最前面,vptr是一个指针。 vtbl(virtua function...

itaiit(https://itaiit.top) 356

Unity3d实现红外热成像效果

1.将需要在红外图像中高亮的物体设置到图层PostProcessing。 2.新建一个相机CameraHighLight,设置其Culling Mask为PostProcessing,也就是在这个相机中只有PostProcessing图层的物体可见。 3.新建一个RenderTexture,命名为HightLightRt,将CameraHighLight的Target Texture设HightLightRt。 4.新建一个相机Camera2,这个相机用于显示其他物体。 接下来将CameraHigh

zouxin_88的专栏 8327

飞腾D2000 BIOS编译避坑指南:PCIE拆分、S3电源与过温保护配置详解

本文详细解析飞腾D2000 BIOS编译中的关键配置技巧,包括PCIE拆分模式优化、S3电源管理适配及过温保护设置。通过实战案例和参数调优建议,帮助开发者规避常见陷阱,充分发挥国产高性能计算平台的硬件潜力。特别针对BIOS编译过程中的隐蔽问题提供解决方案。

weixin_33704234的博客 534

Github干货系列:C++资源集合

Ubuntu12.04的源在 /etc/apt/sources.list  中, 进入 /etc/apt/ 先进行备份 然后用根用户权限打开sources.list。      sudo gedit /etc/apt/sources.list  将下面代码贴进去 #台湾源    deb http://tw.archive.ubuntu.com/ubuntu/ natt

Windeal 2486

CADENCE 25.1打开元件库ERRORCannot perform the operation because of an exception.

摘要:解决CADENCE25.1打开元件库报错"ERRORCannotperformtheoperationbecauseofanexception"的方法:该错误通常由软件中文设置导致。解决方案为:进入Options→Preferences→MorePreferences,取消勾选两个本地语言选项后重启软件即可恢复正常。此方法简单有效,能快速解决因语言设置导致的元件库访问异常问题。(98字)

0 1015

[C++]深度探索C++对象模型——关于默认构造函数

原书第二章第一节的内容 关于Default constructor的概念:没有任何形参的constructor(注意,不是说编译器自动为类添加的才叫Default constructor)。 这一节主要讲了编译器什么时候为类添加Default constructor? 先说结论:四种情况下,编译器会自动合成implicit nontrivial default constructor。 带...

github_38704428的博客 295

Ollama 在不同操作系统上的详细使用,及用python进行调用实战

本文介绍了Ollama的安装配置及Python调用方法。主要内容包括:1)Windows/macOS/Linux/Docker等多种安装方式;2)Ollama基础命令,涵盖模型管理、运行和服务控制;3)Python调用教程,包含官方库使用、自定义客户端、多轮对话、参数设置等高级功能,以及直接API调用示例。文章提供了完整的代码片段,适合开发者快速上手使用Ollama进行本地大模型部署和开发。

数据知道的博客 1233

2026最新openclaw(clawbot/moltbot)真正在自己个人电脑上搭建部署,配置飞书远程远程让AI助理操控电脑完成任务,以及结合ollama无限token实现7*24小时工作(附配置)

2026最新openclaw(clawbot/moltbot)真正在自己个人电脑上搭建部署,配置飞书远程远程让AI助理操控电脑完成任务,以及结合 ollama 无限token实现7*24小时工作,以及部署安装需要的 skills 完成复杂的工作任务(附完整可以运行的配置文件)。 很多人已经会配置安装 openclaw 了 ,但是 安装完成之后真正让电脑自动运行起来的很好,完成出色工作的更少,最常见的就是聊聊天,或者执行一些简单的命令,理解要让电脑自动化工作,openclaw、skills、大模型这三样。

代码讲故事 2963

通过对象指针的方式强行指定到子类_c++对象模型

使用c++有些年头了,有一本深度搜索c++对象模型的书写的很赞,很经典。本文是本书的读书笔记。关于对象加上封装后的布局成本c语言中如下声明一个结构体typedef struct point3d{ float x; float y; float z;}Point3d;struct point3d 转化为class Point3d之后class Point3d{ public: Point3d(flo...

weixin_39517289的博客 94

在SAP系统中创建物料 860000000000000082(物料描述为“8680月球广寒宫坦克车”)时,系统报出了一个错误

摘要:SAP系统创建物料"8680月球广寒宫坦克车"时出现"C+020"错误,提示评估区域C916未在物料分类账中设置为生产性。解决方案需进入"会计-控制-产品成本控制-实际成本核算"路径,将评估区域C916手动设置为生产性状态。该操作需由具备权限的系统管理员或FICO顾问执行,建议操作前进行数据备份或在测试环境验证。完成设置后即可重新创建物料。

金牌架构师 391

深度搜索C++对象模型2.2 构造函数语义学-Default Constructor的构造操作

implicit 暗中的 explicit 显式的 trivial 没用的 no

春秋战车 965

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

深度搜索C++对象模型2.2 构造函数语义学-Copy Constructor的构造操作

Shallow Copy = Bitwise Copy,Deep Copy = Memberwise Copy.

春秋战车 1066

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

深度搜索C++对象模型 - 构造语义学

 深度搜索C++对象模型:  构造,拷贝,析构语义学 //*********************************************************************************************// ---> "构造函数语义学": class A {     public:     virtual ~A() = 0;     v

github_21089181的专栏 473

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

深度搜索C++对象模型(理念总结)

1. 目标: C++的语法规格(C++ 标准)如何具体实现出来的, 即编译器如何理解并构建一系列的数据结构, 去扩充/优化/翻译cpp源代码,然后组成串行指令,确保最终代码能够准确而高效执行. 大致包括1). 编译器功能的思考和设计逻辑                         2).cpp源代码的编译+链接(不用生成汇编)的步骤. 2.构造函数语义学: 遵循语意(C++ 标准

noticmp的专栏 769

对象传参_c++对象模型

使用c++有些年头了,有一本深度搜索c++对象模型的书写的很赞,很经典。本文是本书的读书笔记。关于对象加上封装后的布局成本c语言中如下声明一个结构体typedef struct point3d{ float x; float y; float z;}Point3d;struct point3d 转化为class Point3d之后class Point3d{ public: Point3d(flo...

weixin_32821643的博客 180

深度搜索C++对象模型 - 关于对象

 深度搜索C++对象模型: 关于对象: 在C语言中 "数据" 和 "处理数据的操作(函数)" 是分开来声明的;也就是说 语言本身并没有支持"数据和函数"之间的关联性; 我们把这种程序方法成为"程序性的"; 有一组"分布在各个以功能为导向的函数中"的算法所驱动, 他们处理的是共同的外部数据; 而C++则会考虑使用一种独立的"抽象数据类型" ADT 来实现一些"数据和函数的关联性"; (

github_21089181的专栏 624

C++ STL之查找函数总结

STL中更有很多函数十分常用,其中查找是使用最高频的函数之一,以下针对C++11的查找进行总结。 1.查找(find) 1.1 std::find() 1.1.1 常用形式 //C++20前 template< class InputIt, class T > InputIt find( InputIt first, InputIt last, const T&...

Code by persistence 4600

关于C++里的find查找函数的简单说明

关于C++里的find查找函数 本人小白做一下简单的小结。。 先给一下我用的代码这些代码吧: #include #include using namespace std; int main() { string s1="love our and you our"; string s2="our"; string s3="myself"; string s4

烟大_歇斯底里 4054

常用的STL查找算法

常用的STL查找算法 《effective STL》中有句忠告,尽量用算法替代手写循环;查找少不了循环遍历,在这里总结下常用的STL查找算法; 查找有三种,即点线面: 点就是查找目标为单个元素; 线就是查找目标为区间; 面就是查找目标为集合; 针对每个类别的查找,默认的比较函数是相等,为了满足更丰富的需求,算法也都提供了自定义比较函数的版本; 单个元素查找 find() ...

weixin_34356138的博客 286

深挖C++:类和对象(中)

(先进后出)

xys_678的博客 242

C++移动构造函数详解

移动构造函数是C++11引入的一种特殊构造函数,用于从临时对象(右值)"窃取"资源来初始化新对象,而不是进行昂贵的深拷贝。char* data;public:// 移动构造函数:参数是右值引用 &&// 关键:把源对象的资源置空。

拒绝AI文,努力在AI时代写出感动人心的好文章 391

ThunderKittens 深度解析:一个不基于 MLIR 的 C++ 模板 GPU DSL

Triton 是"让更多人能写 GPU kernel",ThunderKittens 是"让会写的人写得更爽"。前者用 MLIR 换易用性,后者用 C++ 模板换可控性。它们不是替代关系,而是覆盖了 GPU 编程光谱的两端。ThunderKittens 的出现,本质上是对"GPU DSL 必须基于 MLIR"这一默认假设的挑战。编译期类型系统本身就可以是一个强大的 DSL 基础设施,不需要中间 IR,不需要黑盒 pass,也能实现 tile 级抽象和零运行时开销。

Maxwell_Newton的博客 339

跟我学c++中级篇—类型定义的方式

本文系统阐述了编程中类型定义的重要性及c++中的实现方式。重点对比了宏定义、typedef与modern using三种机制,指出using在可读性、灵活性和模板支持上的优势,推荐优先使用。同时提醒开发者注意别名滥用、类型歧义、错误信息冗长等问题,强调统一规范与合理设计。最终结论:在现代c++开发中,应以using为主,兼顾简洁性与可维护性,避免陷入命名混乱与编译困境。

fpcc的专栏 71
上一篇: 深度搜索C++对象模型 - 复制构造函数
下一篇: 深度搜索C++对象模型 - 数据语义学
zhang_yao_wu1993
博客等级 码龄12年 0粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值