C++学习——对象数组、成员对象与封闭类
以下内容源于C语言中文网的学习与整理,非原创,如有侵权请告知删除。
一、对象数组
对象数组,即数组的每个元素都是某个类的对象。
1、对象数组中的每个元素都需要用构造函数初始化,具体哪些元素用哪些构造函数初始化,取决于定义数组时的写法。
请看下面的例子:
#include<iostream>
using namespace std;class CSample{
public:CSample(){ //构造函数 1cout<<"Constructor 1 Called"<<endl;}CSample(int n){ //构造函数 2cout<<"Constructor 2 Called"<<endl;}
};int main(){cout<<"stepl"<<endl;CSample arrayl[2]; //1,1//类似于CSample arrayl[0](),arrayl[1]() ? 有这种写法吗?cout<<"step2"<<endl;CSample array2[2] = {4, 5};//2,2//类似于CSample arrayl[0](4),arrayl[1](5) ? 有这种写法吗?cout<<"step3"<<endl;CSample array3[2] = {3};//2,1cout<<"step4"<<endl;CSample* array4 = new CSample[2];//1,1delete [] array4;return 0;
}
stepl
Constructor 1 Called
Constructor 1 Called
step2
Constructor 2 Called
Constructor 2 Called
step3
Constructor 2 Called
Constructor 1 Called
step4
Constructor 1 Called
Constructor 1 Called
step1的 array1 数组中的两个元素没有指明如何初始化,那么默认调用无参构造函数初始化,因此输出两行 Constructor 1 Called。
step2的 array2 数组进行了初始化,初始化列表 {4, 5} 可以看作用来初始化两个数组元素的参数,所以 array2[0] 以 4 为参数,调用构造函数 2 进行初始化;array2[1] 以 5 为参数,调用构造函数 2 进行初始化。这导致输出两行 Constructor 2 Called。
step3的 array3 指出了 array3[0] 的初始化方式,没有指出 array3[1] 的初始化方式,因此分别用构造函数 2 和构造函数 1 进行初始化。
step4动态分配了一个 CSample 数组,其中有两个元素,没有指出和参数有关的信息,因此这两个元素都用无参构造函数初始化。
2、在构造函数有多个参数时,数组的初始化列表中要显式地包含对构造函数的调用。
例如下面的程序:
class CTest{
public:CTest(int n){ } //构造函数(1)CTest(int n, int m){ } //构造函数(2)CTest(){ } //构造函数(3)
};
int main(){//三个元素分别用构造函数(1)、(2)、(3) 初始化CTest arrayl[3] = { 1, CTest(1,2) };//像{1, (1,2)}这样行不行呢?//三个元素分别用构造函数(2)、(2)、(1)初始化CTest array2[3] = { CTest(2,3), CTest(1,2), 1};//两个元素指向的对象分别用构造函数(1)、(2)初始化CTest* pArray[3] = { new CTest(4), new CTest(1,2) }; //第13行return 0;
}
上面程序中比较容易令初学者困惑的是第 13 行。
pArray 数组是一个指针数组,其元素不是 CTest 类的对象,而是 CTest 类的指针。第 13 行对 pArray[0] 和 pArray[1] 进行了初始化,把它们初始化为指向动态分配的 CTest 对象的指针,而这两个动态分配出来的 CTest 对象又分别是用构造函数(1)和构造函数(2)初始化的。pArray[2] 没有初始化,其值是随机的,不知道指向哪里。
第 13 行生成了两个 CTest 对象,而不是三个,所以也只调用了两次 CTest 类的构造函数。
二、成员对象与封闭类
1、一些概念理解
如果一个类的成员变量是另一个类的对象,则称该成员变量为“成员对象”,而包含成员对象的类叫封闭类(enclosed class)。
2、封闭类的对象的初始化
创建封闭类的对象时,它包含的成员对象也需要被创建,这就会引发成员对象构造函数的调用。成员对象的构造函数可能有很多个(即函数重载),那如何让编译器知道,成员对象到底是用哪个构造函数进行初始化?这就需要借助封闭类构造函数的初始化列表。
一个简单的示例如下:
#include <iostream>
using namespace std;//1、轮胎类
class Tyre{
public:Tyre(int radius, int width);//轮胎类构造函数的声明void show() const;
private:int m_radius; //半径int m_width; //宽度
};
//轮胎类构造函数的定义
Tyre::Tyre(int radius, int width) : m_radius(radius), m_width(width){ }
void Tyre::show() const {cout << "轮毂半径:" << this->m_radius << "吋" << endl;cout << "轮胎宽度:" << this->m_width << "mm" << endl;
}//2、引擎类
class Engine{
public:Engine(float displacement = 2.0);//引擎类构造函数的声明void show() const;
private:float m_displacement;
};
//引擎类构造函数的定义
Engine::Engine(float displacement) : m_displacement(displacement) {}
void Engine::show() const {cout << "排量:" << this->m_displacement << "L" << endl;
}//3、汽车类
class Car{
public:Car(int price, int radius, int width);//汽车类构造函数的声明void show() const;
private:int m_price; //价格Tyre m_tyre;Engine m_engine;
};
//汽车类构造函数的定义
Car::Car(int price, int radius, int width): m_price(price), m_tyre(radius, width){ };//指明m_tyre对象的初始化方式
void Car::show() const {cout << "价格:" << this->m_price << "¥" << endl;this->m_tyre.show();this->m_engine.show();
}int main()
{Car car(200000, 19, 245);//第51行car.show();return 0;
}
价格:200000¥
轮毂直径:19吋
轮胎宽度:245mm
排量:2L
封闭类构造函数的初始化列表,其写法如下:
封闭类的类名::封闭类的构造函数名(参数表): 成员变量名(参数表),…,成员对象名(参数表)
{//TODO:
}
对于封闭类Car,它有一个成员变量m_price,两个成员对象m_tyre 和 m_engine。而且编译器知道第 51 行的 car 这个对象是用 Car(int price, int radius, int width) 这个构造函数进行初始化的。
(1)对于基本类型的成员变量,比如成员变量 m_price 是 int 类型,其“参数表”中只有一个值,就是初始值,在调用构造函数时,会把这个初始值直接赋给成员变量。比如Car类构造函数的初始化列表中,将初始值 price 赋值给成员变量 m_price。
(2)对于成员对象,“参数表”中存放的是构造函数的参数,它可能只有一个值,也可能有多个值,它指明了该成员对象如何被初始化。比如Car类构造函数的初始化列表中,m_tyre(radius, width)告诉编译器,应该以 radius 和 width 作为参数传入构造函数 Tyre(int radius, int width) 中,来初始化m_tyre这个对象。
(3)这里没有说明 m_engine 该如何处理,此时编译器就认为 m_engine 应该用 Engine 类的无参构造函数初始化,而 Engine 类确实有一个无参构造函数(设置了固定参数而视为无参)。
总之,生成封闭类对象的语句,一定要让编译器能够弄明白其成员对象是如何初始化的,否则就会编译错误。在上面的程序中,如果 Car 类的构造函数没有初始化列表,那么第 51 行就会编译出错,因为编译器不知道该如何初始化 car.m_tyre 对象,因为 Tyre 类没有无参构造函数,而编译器又找不到用来初始化 car.m_tyre 对象的参数。
3、成员对象的消亡
封闭类对象生成时,先执行所有成员对象的构造函数,然后才执行封闭类自己的构造函数。成员对象构造函数的执行次序和成员对象在类定义中的次序一致,与它们在构造函数初始化列表中出现的次序无关。
当封闭类对象消亡时,先执行封闭类的析构函数,然后再执行成员对象的析构函数,成员对象析构函数的执行次序和构造函数的执行次序相反,即先构造的后析构,这是 C++ 处理此类次序问题的一般规律。
#include<iostream>
using namespace std;class Tyre {
public:Tyre() { cout << "Tyre constructor" << endl; }~Tyre() { cout << "Tyre destructor" << endl; }
};class Engine {
public:Engine() { cout << "Engine constructor" << endl; }~Engine() { cout << "Engine destructor" << endl; }
};class Car {
private:Engine engine;Tyre tyre;
public:Car() { cout << "Car constructor" << endl; }~Car() { cout << "Car destructor" << endl; }
};int main() {Car car;return 0;
}
Engine constructor
Tyre constructor
Car constructor
Car destructor
Tyre destructor
Engine destructor
相关文章:
C++学习——对象数组、成员对象与封闭类
以下内容源于C语言中文网的学习与整理,非原创,如有侵权请告知删除。 一、对象数组 对象数组,即数组的每个元素都是某个类的对象。 1、对象数组中的每个元素都需要用构造函数初始化,具体哪些元素用哪些构造函数初始化,…...
解锁机器学习-梯度下降:从技术到实战的全面指南
目录 一、简介什么是梯度下降?为什么梯度下降重要? 二、梯度下降的数学原理代价函数(Cost Function)梯度(Gradient)更新规则代码示例:基础的梯度下降更新规则 三、批量梯度下降(Batc…...
day62:ARMday9,I2c总线通信
作业:按键中断实现LED1、蜂鸣器、风扇 key_in.c: #include "key_in.h"void gpio_init() {//RCC使能//GPIOERCC->MP_AHB4ENSETR | (0x1<<4);//GPIOBRCC->MP_AHB4ENSETR | (0x1<<1);//PE10、PB6、PE9输出模式GPIOE->MODER & ~(0…...
【Python学习笔记】类型/运算/变量/注释
前言 人生苦短,追求生产力,做一只时代风口的猪,应该学python Python语言中,所有的数据都被称之为对象。 1. 对象类型 Python语言中,常用的数据类型有: 整数, 比如 3 小数(也叫浮…...
国内常用源开发环境换源(flutter换源,python换源,Linux换源,npm换源)
flutter换源 使用环境变量:PUB_HOSTED_URL FLUTTER_STORAGE_BASE_URL, upgrade出问题时可能会提示设置FLUTTER_GIT_URL变量。 flutter中国 PUB_HOSTED_URLhttps://pub.flutter-io.cn FLUTTER_STORAGE_BASE_URLhttps://storage.flutter-io.cn FLUTTER_GIT_URLhtt…...
关于一篇什么是JWT的原理与实际应用
目录 一.介绍 1.1.什么是JWT 二.结构 三.Jwt的工具类的使用 3.1. 依赖 3.2.工具类 3.3.过滤器 3.4.控制器 3.5.配置 3.6. 测试类 用于生成JWT 解析Jwt 复制jwt,并延时30分钟 测试JWT的有效时间 测试过期JWT的解析 四.应用 今天就到这了,希…...
【Method】把 arXiv论文 转换为 HTML5 网页
文章目录 MethodReference https://ar5iv.labs.arxiv.org/ Articles from arXiv.org as responsive HTML5 web pages. 可以将来自 arXiv 的 PDF 论文渲染成 HTML5 网页版本。 Method View any arXiv article URL by changing the X to a 5. 将 arXiv 网址中的 x 换成 5 再回…...
每日一题AC
4.小花和小草正在沙滩上玩挖沙洞的游戏。他们划了一条长度为n米的线作为挖沙洞的参考线路,小花和小草分别从两头开始沿着划好的线开始挖洞,小花每隔a米挖一个洞,小草每隔b米挖一个洞,碰到已经挖过洞的就不需要再挖了。那么&#x…...
后端:推荐 2 个 .NET 操作的 Redis 客户端类库
目录 Redis特点 Redis场景 1. StackExchange.Redis 2. FreeRedis 🚀 快速入门 🎣 Master-Slave (读写分离) 💻 Pipeline (管道)示例 🌌 Redis Cluster (集群) Redis ,是一个高性能(NOSQL)的key-value数据库,Re…...
华泰证券:京东营收增长或短期承压
来源:猛兽财经 作者:猛兽财经 猛兽财经获悉,华泰证券近期发布研报称京东营收增长或短期承压。华泰证券主要观点如下:营收增长或短期承压,聚焦长期内生能力建设 考虑到消费情绪的恢复仍需一定时间,我们预计…...
Java从resources文件下载文档,文档没有后缀名
业务场景:因为公司会对excel文档加密,通过svn或者git上传代码也会对文档进行加密,所以这里将文档后缀去了,这样避免文档加密。 实现思路:将文档去掉后缀,放入resources下,获取输入流࿰…...
【动手学深度学习-Pytorch版】BERT预测系列——BERTModel
本小节主要实现了以下几部分内容: 从一个句子中提取BERT输入序列以及相对的segments段落索引(因为BERT支持输入两个句子)BERT使用的是Transformer的Encoder部分,所以需要需要使用Encoder进行前向传播:输出的特征等于词…...
Python之元组、字典和集合练习
1、餐厅下午茶 (列表与元组 crr66) 某餐厅推出了优惠下午茶套餐活动。顾客可以以优惠的价格从给定的糕点和给定的饮 料中各选一款组成套餐。已知,指定的糕点包括松饼(Muffins)、提拉米苏(Tiramisu)、芝士蛋 糕(Cheese Cake)和三明治(Sandwic…...
【数据结构】归并排序和计数排序(排序的总结)
目录 一,归并排序的递归 二,归并排序的非递归 三,计数排序 四,排序算法的综合分析 一,归并排序的递归 基本思想: 归并采用的是分治思想,是分治法的一个经典的运用。该算法先将原数据进行拆…...
某医疗机构:建立S-SDLC安全开发流程,保障医疗前沿科技应用高质量发展
某医疗机构是头部资本集团旗下专注大健康领域战略性投资与运营的实业公司,市场规模超300亿。该医疗机构已完成数字赋能,形成了标准化、专业化、数字化的疾病和健康管理体系,将进一步规划战略方向,为人工智能纳米技术、高温超导、生…...
验证二叉搜索树的后序遍历序列
LCR 152. 验证二叉搜索树的后序遍历序列 class VerifyTreeOrder:"""LCR 152. 验证二叉搜索树的后序遍历序列https://leetcode.cn/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/description/"""def solution(self, postorder: Lis…...
第三章 内存管理 一、内存的基础知识
目录 一、什么是内存 二、有何作用 三、常用数量单位 四、指令的工作原理 五、装入方式 1、绝对装入 2、可重定位装入(静态重定位) 3、动态运行时装入(动态重定位) 六、从写程序到程序运行 七、链接的三种方式 1、静态…...
【Java学习之道】Java常用集合框架
引言 在Java中,集合框架是一个非常重要的概念。它提供了一种方式,让你可以方便地存储和操作数据。Java中的集合框架包括各种集合类和接口,这些类和接口提供了不同的功能和特性。通过学习和掌握Java的集合框架,你可以更好地管理和…...
logicFlow 流程图编辑工具使用及开源地址
一、工具介绍 LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow 支持前端研发自定义开发各种逻辑编排场景,如流程图、ER 图、BPMN 流程等。在工作审批配置、机器人逻辑编排、无…...
ATF(TF-A)/OPTEE之动态代码分析汇总
安全之安全(security)博客目录导读 1、ASAN(AddressSanitizer)地址消毒动态代码分析 2、ATF(TF-A)之UBSAN动态代码分析 3、OPTEE之KASAN地址消毒动态代码分析...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
