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

C++编译器会对没有构造函数的类生成默认构造函数吗? 之前在上C++的课的时候,印象中有那么一句话: 如果一个类没有任何构造函数,那么编译器会生成一个默认的构造函数 今天在看《深度探索C++对象模型》的第二章:“构造函数语意学”的时候发现之前听到的说法是错误的。 比如说如下代码: class A { public: int a; }; int main(void) { A a; a.a = 4; A a2; ... 阅读详情

原书第二章第一节的内容

关于Default constructor的概念:没有任何形参的constructor(注意,不是说编译器自动为类添加的才叫Default constructor)。

这一节主要讲了编译器什么时候为类添加Default constructor?

先说结论:四种情况下,编译器会自动合成implicit nontrivial default constructor。

  1. 带有Default constructor的member class object
  2. 带有Default constructor的Base class
  3. 带有Virtual function
  4. 带有Virtual base class

情况一:带有Default constructor的member class object

比如类A的某个成员变量是类B的一个对象,而类B是有Default constructor的,比如:

class Foo{public: Foo(); Foo(int); ...};
class Bar{public: Foo foo; char *str; ...};

这种情况下,Bar没有(显式地)定义自己的Default constructor,编译器会自动合成一个。合成出来的Default constructor也许类似下面的形式:

Bar::Bar()
{
    foo.Foo::Foo();
}

说明:

  1. 编译器在这里完成了对类成员对象的默认构造(调用了foo的默认构造函数),这属于编译器的职责。但是没有对str变量进行初始化(比如也许程序要求str=0),因为这属于类Bar的设计者(程序员)的工作。
  2. 如果类已经显式声明了一个default constructor并在其中对str初始化了。这时编译器会扩张原有的default constructor(实际上,会扩张所有的显式定义的constructor),在constructor的user code之前调用类成员对象的constructor。
  3. 如果一个类有多个member class objects,按照声明的顺序,扩张constructor的时候依次调用这些类成员变量的constructor。

情况二:带有Default constructor的Base class

如下:

class Base{public: Base(); ...};
class A : public Base{...};

说明:

  1. 如果类A没有任何constructor。编译器会自动合成一个Default constructor,然后调用Base的Default constructor。
  2. 如果类A有多个已定义的constructor。即使已定义的constructor中没有Default constructor,编译器也不会合成一个Default constructor,只会扩张每个已有的constructor,调用Base的Default constructor。

情况三:带有Virtual function

带有虚函数(自己定义的,或者继承而来的)时,需要对vtbl(虚函数表)和vptr(指向虚函数表的指针)进行相应设置以支持多态。

  1. 如果类没有任何constructor,编译器会自动合成一个Default constructor,完成对vtbl和vptr的设置。
  2. 如果类定义了constructor,编译器会扩展这些constructor,完成对vtbl和vptr的设置。

情况四:带有Virtual base class

与情况三类似,为了支持虚基类,编译器需要做一些工作。

 

总结:

这个四种情况下被合成出来的constructor只能满足编译器的需要(而不是程序需要)。可以看出来这四种情况要么调用了类成员或者基类的Default constructor,要么是为了支持virtual机制。

不满足这四种情况时,实际上不会合成一个Default constructor。常见误解会认为如果类没有定义Default constructor,编译器就会自动合成一个,这是不对的。

还有一点值得注意:合成的Default constructor只会初始化那些有构造函数的成员变量。对于整数、数组、指针等基本类型,编译器合成的Default constructor不会处理。所以,又有一个误解认为编译器合成的Default constructor会为我们自动初始化所有的类成员变量,这也是错的。

深度探索C++对象模型 超高清pdf 深度探索C++对象模型 超高清 立即下载

相关推荐

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

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

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

 深度搜索C++对象模型:  Function Semantics C++支持三种类型的 member function: static nonstatic virtual; 后文分析他们的差异 //*********************************************************************************************//

github_21089181的专栏 543

01 AUTOSAR CP标准文档阅读指南

01 AUTOSAR CP标准文档阅读指南

汽车软件工程师 | 好奇博主 | 处女座 1134

深度探索C++对象模型

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

surfaceyan的博客 1825

基于wxWidgets框架,使用DialogBlocks建立OpenGL界面

前言 之前公司要求使用wxWidgets做GUI,基于OpenGL图形内核,开发三维可视化工具。目前初步开发工作基本已经完成,剩下都是完善了。这里记录一下最开始的框架搭建过程(当然是简化版啦)。wxWidgets结合OpenGL开发可以实现跨平台应用,再结合CMake和VS Code,整体开发工具用习惯了会感觉非常顺手。 界面编辑 首先,使用DialogBlocks新建一个工程,这里工程目录...

cyberobot的博客 2750

超详细流式细胞术全流程解析:从样本制备到结果分析全攻略

流式细胞术(Flow Cytometry)是现代生物学和医学研究中不可或缺的高通量分析技术,可实现对细胞表型、功能状态、细胞周期等多维度参数的快速检测。本文将从实验全流程出发,详解样本制备、上机操作、参数设置及结果处理的核心要点,帮助科研人员精准掌握流式实验关键技术。

good_rrrrr的博客 3868

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

Unity中URP实现水体效果(泡沫)

在上篇文章中,我们实现了水体的深度。在这篇文章中,我们来使用上篇文章采样后的深度图来实现水中的泡沫效果。

楠溪泽岸的博客 3489

深度解读《深度探索C++对象模型》之C++默认构造函数

C++的默认构造函数的作用是什么?什么时候会需要一个默认构造函数,以及默认构造函数从哪里来?这篇文章将从编译器的角度来分析这个问题。

iShare_Carlos的博客 1377

BACnet/IP BBMD跨网段通信深度解析与最佳实践

本文介绍了在BACnet/IP网络中通过BBMD实现跨子网设备通信的关键配置方法。重点阐述了广播分发表(BDT)中掩码设置的重要性:使用子网掩码(255.255.255.0)会导致路由器拦截广播消息,而必须采用主机掩码(255.255.255.255)才能启用单播隧道机制,使BACnet广播消息封装为可路由的单播UDP包。文章详细说明了BDT条目的正确配置格式、BIP广播地址的作用,并提供了验证步骤,强调在跨网段场景中,正确设置掩码是确保设备发现和通信成功的关键因素。

零一架构师的专栏 1536

传感器使用——ESP-WROOM-32 and INMP441麦克风音频采集

传感器使用——ESP-WROOM-32 and INMP441麦克风音频采集,数据显示及matlab操作界面。

qq_41958946的博客 7354

深度探索C++对象模型:默认构造函数

默认构造函数在被需要的时候被编译器产生出来。 这句话的关键部分是: 被谁需要? 什么时候被需要? 做什么事情? 被谁需要? 编译器为程序构建默认构造函数是因为编译器需要它,而不是因为程序需要它。程序需要什么应该是程序员的责任,应该由程序员提供。举个例子,例如下面这段代码: class Foo { public: int val; Foo* pnext; } void foo_bar() { Foo bar; // 程序需要 bar's members 都被初始化为

qq_43351159的博客 275

ComfyUI 汉化教程(中文界面)

如果你对翻译的结果不满意,还可以进行修改。首先,进入目录,可以看到该目录中有很多 JSON 文件:打开 JSON 文件,找到要修改的内容,修改对应的Value值即可:最后,重启 ComfyUI 即可。

水滴的博客 1万+

《深度探索C++对象模型》(一)对象模型、存储形式;默认构造函数一定会构造么?

一)、读后感     在我参加工作两年多的时候,工作不算很忙了,《深入理解C++对象模型》开始进入我的视野;或许是因为我要从Symbian.C++ 转向iOS Objective-C,并开始思考语言本身的一些东西的缘故。     其实在一年前,出于对C++的迷惑,我已经买了这本书。当时翻了几页竟然没懂,就搁那儿了!可是现在,它让我随身携带、流连忘返、是个旅途好伴侣;看到它我精神抖擞,它给了我继

郭晓东的专栏 6336

29.Labview界面设计 --- (下篇)自定义控件库、界面布局与外观设计

1.自定义控件外观(自定义控件)1.1 自定义外观库1.2 手动自定义控件外观2. 前面板控件布局方式(控件排布)2.1 模块化控制布局方式2.2 数据采集布局方式3. 前面板外观优化项(背景设计)3.1 前面板背景设计3.2 前面板窗口整理本节第一部分教大家安装一种可以直接用的自定义控件库,第二部分教大家如何自己设计控件并保存调用。

关注我,更多技术问题欢迎私聊~ 4782

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

[深度探索C++对象模型] 默认构造函数和拷贝构造函数的构造操作

(1)何时编译器会合成一个默认构造函数? (2)默认构造函数做什么? (3)何时会调用拷贝构造函数? (4)什么情况下会合成拷贝构造函数呢?

追寻梦想的青春 1452

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

深度探索C++ 对象模型(3)-默认构造函数Default Constructor

1. Default Constructor只对base class subobjects和member class objects初始化,对data member不做操作 2. 编译器构造Default Constructor 只在下面4种case: 包含有带默认构造函数的对象成员的类 . 继承自带有默认构造函数的基类的类 . 有虚函数的类(需要初始化每一个class object的vptr) . 有一个虚基类的类 1.包含有带默认构造函数的对象成员的类 class Foo { publ

thefist的专栏 536

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

《深度探索C++对象模型》- 编译器合成默认构造函数

原文地址: http://blog.youkuaiyun.com/ljianhui/article/details/46247897编译器需要的时候是遇到如下四种情况的时候,它需要为以下四种类型的类合成一个默认的构造函数: 1)类的成员变量带有默认构造函数 2)类的基类带有默认构造函数 3)类带有virtual函数 4)类带有一个virtual基类 且合成操作只有在构造函数真正需要被调用时

master-dragon的专栏 719

深度探索C++ 对象模型(3)-默认构造函数Default Constructor续

(1)带有虚函数的类 class Widget { public: virtual int flip() = 0; //.. }; void flip(const Widget* widget ) { widget->flip(); } //假设Bell和Whistle都派生自Widget void main() { Bell bell; Whistle w; flip(bell); flip(w); } 编译器的工作为: 1).生成一个虚函数表vtbl,内

thefist的专栏 384

《深度探索c++ 对象模型》有感之默认构造函数,拷贝构造函数,拷贝运算符的合成

一般情况下,定义一个class的时候,理论上,编译器可能这个类合成很多东西 有default constructor ,copy constructor ,copy assignment operator, 分别是默认构造函数,拷贝构造函数,拷贝指定运算符

dalleny的专栏 1285

当前类没有默认构造函数,但成员对象有默认构造函数(整理自深度探索C++对象模型 的41页)

当前类没有默认构造函数,但成员对象有默认构造函数 class Foo { public: Foo();//default constructor Foo(int); ... }; class Bar//自己没有默认构造函数,但其成员对象foo有默认构造函数. { public: Foo foo;//这个时候Bar::foo需要被初始化 private: int n; }; //此时编译器会自动为Bar合成一个默认构造函数(不可见) Bar::Bar() { //伪代码,会

Stephen___Qin的博客 353

深度探索C++对象模型--------默认构造函数

一:默认构造函数的构建 默认构造函数总是在被需要的时候构建出来!!关键字“被需要的时候”!! class Foo { public: int val; Foo *next; }; void foo_bar() { Foo bar; if(bar.val || bar.next) //do something ...

weixin_34400525的博客 89

《深度探索C++对象模型》阅读笔记(完整版)

《深度探索C++对象模型》完整阅读笔记

2401_82413779的博客 1903

C++ 合成默认构造函数的真相

   对于C++默认构造函数,我曾经有两点误解: 类如果没有定义任何的构造函数,那么编译器(一定会!)将为类定义一个合成的默认构造函数。 合成默认构造函数会初始化类中所有的数据成员。   第一个误解来自于我学习C++的第一本书 《C++ Primer》,在书中392页:“只有当一个类没有定义构造函数时,编译器才会自动生成一个默认构造函数”。 实际上这句话也没有说错,它说明了...

weixin_30750335的博客 68

C++对象模型,默认构造函数、拷贝构造函数

C++对象模型,默认构造函数、拷贝构造函数 C++ 对象模型演进 以下内容属于本人自己的学习笔记,参考资料是大名鼎鼎的 《深度C++探索对象模型》,如有错误欢迎指出 名词解释 侯捷老师在翻译的时候就保留了大量的英文名词,这样表达起来其实会更加清楚一点 详情 请访问飞书文档 ...

mixinju的优快云博客 681
上一篇: [C/C++]中按位“与”“或”“异或”的优先级比“==”低
下一篇: 设计模式学习笔记1——单例模式
dummy_bot
博客等级 码龄10年 35粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值