C++ 经验条款

本文深入探讨了C++中构造函数与虚函数的使用细节,强调了构造函数不应成为虚函数,详细解释了默认构造函数的生成规则及特殊情况。同时,文章提供了关于拷贝构造函数调用、析构顺序、类对象大小决定因素、虚继承影响、运算符重载注意事项等关键概念的见解。最后,阐述了传参调用、引用传参、指针传参的区别和联系,以及如何正确理解C++中这些核心概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++经验谈:

一、绝不让构造函数称为虚函数:

         从最简单的思想来看,C++对象模型中是根据虚函数表来管理虚函数的,那么在调用虚函数时,需要找到虚函数表,在对象没有创建成功时是没有虚函数表指针的,构造函数就是构造对象的,在对象没有创建成功之前来寻找虚函数表是不合理的。

         一般情况下,编译器会为每个类生成一个公有的默认构造函数,但是有两种特殊情况例外:

         一个类显示声明了构造函数,这种情况下编译器不会生成公有默认构造函数,如果程序需要一个默认构造函数,则需要程序员显示地提供。

         一个类声明了一个非Public的构造函数,编译器不会生成公有的默认构造函数。

         如果类有继承,那么首先完成基类的构造,再完成继承类的构造,在析构时,顺序相反。

         如果基类有virtual函数,那么在继承类的构造中还需要有虚函数表的创建。

 

         关于拷贝构造函数的调用:

         当类的一个对象去初始化该类的另一个对象时,拷贝构造函数会被调用。

         如果函数的形参是类的对象,调用函数进行形参和实参的结合时,拷贝构造函数会被调用。

         如果函数的返回值是类对象,函数调用完成返回时,拷贝构造函数会被调用。

 

避免在构造/析构函数中调用虚函数:

         基类的构造函数会在派生类构造函数执行之前被调用,所以当基类构造函数运行时,派生类的数据成员都没有进行初始化。

         虚函数的调用机制完全由基类控制,所以如果基类没有完成构造,虚函数的调用机制(既虚函数表)没有完成初始化,通过虚函数实现的所有期望操作都将失败。

 

Class对象大小与什么有关系:

         如果一个class中无任何数据成员,那class的大小时1.

         Class中对象的大小仅与对象的数据成员大小有关系,而与对象的函数成员无任何关系。

         Class对象非静态数据成员占用内存大小会影响对象大小

         Class对象采用的内存对齐策略会影响类对象大小

         Class对象中数据成员不会影响对象大小

         Class中virtual函数会影响类对象大小,因为virtual-talbe的原因虚函数占4字节空间

关于虚继承影响对象大小:

         由于涉及虚函数表和虚基表,会同时增加一个(剁成继承下对应多个)vfptr指针指向虚函数表vftable和一个vbptr指针指向虚基表vbtable,这两者所占的空间大小为:8(或者8乘以多继承时父类的个数),记住有各自的虚函数表指针和虚基类指针,都共享虚基类指针即可。

         类对象的大小影响因素不包括静态数据成员,因为累中的静态数据成员分布于全局存储区域,不占用类对象的空间。

 

运算符重载:

         不要重载&&和||运算符,因为重载&&和||,会导致&&和||失去简短求值功能。

         如果一个重载操作符是类成员,那么只有当和它一起被使用的左操作数是该类对象时,它才会被调用。如果该操作符的左操作数必须是其他类型,那么重载操作符必须是命名空间成员。

 

Public private protected三种继承方法:

         Public继承时最常用的继承机制,public继承时子类具有最大的权限,公有继承的特点是基类公有成员和保护成员作为派生类的成员时,他们都保持原有的状态,而基类的私有成员仍然是私有的。

         Protected是一种比较有特点的继承机制。保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元函数访问,基类的私有成员仍然是私有的。

         Private是一种比较少见的继承方法,私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。

 

         单继承在构造时,首先是构造基类,然后是进程自身的构造。如果基类仍然存在上层基类,则首先进行上层基类的构造,然后再构造基类,析构的顺序和构造的顺序是严格按照构造顺序的逆序进行的。

 

         不要重新定义继承而来的非虚函数,以防止产生函数覆盖现象。

 

         带默认参数的virtual函数实现时,虚函数采用动态绑定,默认参数采用静态绑定。在基类虚函数中声明的默认参数,即使派生类中重新指定了默认参数,在多态调用时,依然采用基类虚函数中的默认参数

 

         不要试图尝试重载虚函数。


 传值调用、引用传值、指针传值三种方式的区别和联系:

1、  值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即使堆栈中开辟内存空间以存放由主调函数传进来的实参值,从而成为实参的一个副本,值传递的特点是被调函数对形式参数的任何操作都作为局部变量进行,不会影响主调函数的实参变量的值,如果想通过传值方式实现两数据的交换,这种方法不可取。

2、  引用传递过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调用函数对形参的任何操作都被处理成指针间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做任何操作都影响主调函数中的实参变量。

3、  指针传递时传值调用的特例,即传的值为主调函数变量的地址。被调函数的形式参数同样在堆栈中为局部变量开辟了内空间,被调函数对局部变量的任何操作都会作用在主调函数变量的地址之上。因此被调函数通过局部形参所做的任何操作都会影响主调函数中的实参变量。

 传值调用、引用传值、指针传值三种方式的区别和联系:

1、  值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即使堆栈中开辟内存空间以存放由主调函数传进来的实参值,从而成为实参的一个副本,值传递的特点是被调函数对形式参数的任何操作都作为局部变量进行,不会影响主调函数的实参变量的值,如果想通过传值方式实现两数据的交换,这种方法不可取。

2、  引用传递过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调用函数对形参的任何操作都被处理成指针间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做任何操作都影响主调函数中的实参变量。

3、  指针传递时传值调用的特例,即传的值为主调函数变量的地址。被调函数的形式参数同样在堆栈中为局部变量开辟了内空间,被调函数对局部变量的任何操作都会作用在主调函数变量的地址之上。因此被调函数通过局部形参所做的任何操作都会影响主调函数中的实参变量。


资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值