组合和聚合

不是c++的语法要求,是一种建模思想

目录

1.组合 

1. 使用 -- 在一个类中创建另外一个类的对象

代码中的解释: 

代码结果: 

组合:

 2. 使用  --  在一个类中创建另外一个类的指针

2.使用类定义一个指针 -- 不是创建一个对象

3.聚合

1. 使用 

代码中的解释: 

结果: 

聚合:

1.组合 

1. 使用 -- 在一个类中创建另外一个类的对象

就是,一个类中包含有另外一个类创建的对象。(则这两个类就是组合关系) 

根据下面代码说明组合的关系。 

// 实现创建两个类,使用类文件分离的方式
testCPU.h:class testCPU{public:// 使用指针传入字符串testCPU(const char *versionCpu = "intel");void setCpu(const char* versionCpu);~testCPU();private:string  versionCpu;  // CPU的类型};testComputer.h:#include "testCPU.h" // 导入Ccpu头文件使用其构造函数class testComputer{public:// 使用指针传字符串更加的高效,并且可以直接复制给string类型testComputer(const char *version="len",int memory = 64,const char*                                                                     versionCpu = "intel");~testComputer();private:int memory;  // 电脑的内存大小testCPU cpu;  // 在testComputer内部创建testCPU类对象};testComputer.cpp:testComputer::testComputer(const char* version, int memory, const char* versionCpu ){this->cpu.setCpu(versionCpu);cout << __FUNCTION__ << endl;  // 打印调用函数的名字}testComputer::~testComputer() {cout << __FUNCTION__ << endl;}testCPU.cpp:testCPU::testCPU(const char* versionCpu){cout << __FUNCTION__ << endl;  // 打印函数的名字}void testCPU::setCpu(const char* versionCpu) {this->versionCpu = versionCpu;}testCPU::~testCPU(){cout << __FUNCTION__ << endl;  // 打印函数的名字}main.cpp:void test() {testComputer com; //使用测试函数,测试组合的规则}int main(void){test();system("pause");return 0;}
代码中的解释: 

1.  当我们使用string定义字符串时,在传递参数的时候,可以使用char* 来传递一个字符串的地址,然后赋值给string类型的变量。 (更加高效)

2.  我们在Computer类中创建了一个CPU类对象。 

3. 在使用有参构造函数的时候,我们使用了默认值通过指定一个默认值,保证我们在不传递数据的情况下也可以有一个值。 (在使用默认值的情况下,我们可以不传递参数的情况下调用有参构造函数。如上面,testCpu cpu 没有使用参数,但是调用的是有参构造函数,因为我们指定了默认值--但是,有默认构造函数的时候就不能这样写了,会出错)

4. 在构造函数和析构函数中,使用__FUNCTION__宏来输出调用的函数名,用来观察组合的关系。 

代码结果: 

 

组合:

在一个类中创建另外一个类的对象 ,然后这两个类会同生共死,当包含的类创建对象时,会先创建被包含类的对象,当包含类对象死亡时,被包含的类的对象也死亡 。

就相当于,你买了一台电脑,电脑里面的cpu也一起被你买到,当你不使用这台电脑的时候,里面的cpu你也不用了。 

 2. 使用  --  在一个类中创建另外一个类的指针

这种情况, 就是在类中不创建对象,定义一个指向该类的指针。testCPU *cpu。因为定义的是指针,不会调用构造函数,所以要想实现组合就得在构造函数中,为指针开辟空间。在析构函数中释放指针的空间。

 

2.使用类定义一个指针 -- 不是创建一个对象

首先,使用类定义一个指针的时候是不会调用构造函数的。因为:它只是定义了一个指针,这个指针指向这个类型,并不表示创建了一个对象。 -- 其实指针是一个整形变量。

这就是为什么我们上面使用在类中定义另外一个类的指针的时候,需要自己在函数中实现开辟空间和释放空间。 

 

3.聚合

1. 使用 

// 实现创建两个类,使用类文件分离的方式
testCPU.h:class testCPU{public:// 使用指针传入字符串testCPU(const char *versionCpu = "intel");void setCpu(const char* versionCpu);~testCPU();private:string  versionCpu;  // CPU的类型};testComputer.h:class testCPU;  // 不导入头文件,告诉编译器要使用这个类就行,(因为没有使用类中的内容,只用了类名)class testComputer{public:testComputer(testCPU *cpu);  // 有参数的构造函数,传入指向对应类型的指针void setCpu(testCPU* cpu);~testComputer();private:testCPU *cpu;  // 定义一个指向类的指针,并不创建对象};testComputer.cpp:testComputer::testComputer(testCPU* cpu){this->cpu = cpu;cout << __FUNCTION__ << endl;}testComputer::~testComputer() {cout << __FUNCTION__ << endl;}void testComputer::setCpu(testCPU* cpu) {this->cpu = cpu;}testCPU.cpp:testCPU::testCPU(const char* versionCpu){cout << __FUNCTION__ << endl;  // 打印函数的名字}void testCPU::setCpu(const char* versionCpu) {this->versionCpu = versionCpu;}testCPU::~testCPU(){cout << __FUNCTION__ << endl;  // 打印函数的名字}main.cpp:#include "testComputer.h" #include "testCPU.h"  // 因为testComputer中不包含此头文件,所以需要再此处包含头文件using namespace std;void test(testCPU* cpu) {testComputer com(cpu); //使用测试函数,测试组合的规则}int main(void){testCPU cpu;  // 创建一个cpu的对象test(&cpu);system("pause");return 0;}
代码中的解释: 

1. 聚合的代码和组合的代码CPU那块是一样的,因为他值需要定义一个类。 

2. 我们在Computer类中定义了一个CPU类的指针,只使用到了CPU这个类的名称,并没有使用类中的内容所以我们不需要包含它的头文件,只需要写一个类的声明就行。(更高效--但是需要使用类中内容的时候,就必须得包含了,比如使用构造函数创建对象) 。 

3. 和组合不一样,聚合我们需要在主程序创建CPU类对象,所以需要包含其头文件。 

4. 我们定义了一个指向CPU类对象的指针,通过构造函数传入,就可以使用这个指针指向传进来的对象。 

结果: 

 

根据结果:看出,当Computer创建的时候,并不会创建CPU,在Computer死亡的时候,也CPU不会死亡。-- 也就是他两的生存和死亡没有关系。 

就好比:你买了一个电脑,但是里面没有CPU,但是有一个可以安装CPU的接口,你又另外买了一个CPU,安装在电脑上。当你的电脑不使用了,你的cpu还可以继续使用,你可以将它拆下来安装到别的电脑上继续使用。 

聚合:

聚合其实就是,在一个类里面定义一个别的类的指针,然后在需要的时候(可以是初始化的时候,也可以不初始化,在后面使用接口(代码中的setCPU函数)再指向),将这个类内部的指针,指向另外一个类的对象。 

所以,聚合就是,类内部有一个指针,用于指向其它类的对象。当我们需要的时候将这个指针,指向这个对象就行。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/616001.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python自动化测试数据驱动解决数据错误

数据驱动将测试数据和测试行为完全分离&#xff0c;实施数据驱动测试步骤如下&#xff1a; A、编写测试脚本&#xff0c;脚本需要支持从程序对象、文件或者数据库读入测试数据&#xff1b; B、将测试脚本使用的测试数据存入程序对象、文件或者数据库等外部介质中&#xff1b;…

密码输入检测 - 华为OD统一考试

OD统一考试(C卷) 分值: 100分 题解: Java / Python / C++ 题目描述 给定用户密码输入流input,输入流中字符 ‘<’ 表示退格,可以清除前一个输入的字符,请你编写程序,输出最终得到的密码字符,并判断密码是否满足如下的密码安全要求。 密码安全要求如下: 密码长度&…

浅研究下 DHCP 和 chrony

服务程序&#xff1a; 1.如果有默认配置&#xff0c;请先备份&#xff0c;再进行修改 2.修改完配置文件&#xff0c;请重启服务或重新加载配置文件&#xff0c;否则不生效 有些软件&#xff0c;安装包的名字和系统里服务程序的名字不一样&#xff08;安装包名字&#xff1a;…

【Spring Cloud】Sentinel流量限流和熔断降级的讲解

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《Spring Cloud》。&#x1f3af;&#x1f3af; &am…

golang 反序列化出现json: cannot unmarshal string into Go value of type model.Phone

项目场景&#xff1a; 今天在项目公关的过程中&#xff0c;需要对interface{}类型进行转换为具体结构体 问题描述 很自然的用到了resultBytes, _ : json.Marshal(result)&#xff0c;然后对resultBytes进行反序列化转换为对应的结构体err : json.Unmarshal(resultBytes, &…

OpenCV-Python(35):BRIEF算法

算法介绍 BRIEF&#xff08;Binary Robust Independent Elementary Features&#xff09;是一种用于计算机视觉中特征点描述子的算法。它是一种二进制描述子&#xff0c;通过比较图像上不同位置的像素值来生成特征点的描述子。 BRIEF算法的基本思想是选取一组固定的像素对&…

12GoF之代理模式

解决问题的思维&#xff1a;AOP 解决问题技术&#xff1a;代理技术 代理技术太麻烦&#xff0c;因此使用框架 Spring AOP框架&#xff08;底层是代理技术&#xff1a;jdk动态daili&#xff0c;cglib&#xff09; 代理模式是GoF23种设计模式之一。属于结构型设计模式。 代理…

做一个个人博客第一步该怎么做?

做一个个人博客第一步该怎么做&#xff1f; 好多零基础的同学们不知道怎么迈出第一步。 那么&#xff0c;就找一个现成的模板学一学呗&#xff0c;毕竟我们是高贵的Ctrl c v 工程师。 但是这样也有个问题&#xff0c;那就是&#xff0c;那些模板都&#xff0c;太&#xff01;…

C 语言每日一题——旋转数组的最小数字

一、题目内容 提供一下该OJ题的链接&#xff1a;旋转数组的最小数字_牛客题霸_牛客网 (nowcoder.com) 二、题目分析 通过示例1可知&#xff0c;我们写代码的目的是在数组中找到一个最大值&#xff0c;并且返回来&#xff1b; 我们很容易的会想到创建一个变量&#xff1a;int…

【Linux】 nohup命令使用

nohup命令 nohup是Linux和Unix系统中的一个命令&#xff0c;其作用是在终端退出时&#xff0c;让进程在后台继续运行。它的全称为“no hang up”&#xff0c;意为“不挂起”。nohup命令可以让你在退出终端或关闭SSH连接后继续运行命令。 nohup 命令&#xff0c;在默认情况下&…

pyx文件编译为pyd/so文件(分别在windows/linux系统下)

Python有以下几种类型的文件&#xff1a; py&#xff1a;Python控制台程序的源代码文件pyx&#xff1a;是Python语言的一个编译扩展&#xff0c;它实际上是Cython语言的源代码文件&#xff08;可以理解为既支持Python语言也支持C/C&#xff09;。pyc&#xff1a;Python字节码文…

DevOps搭建(十六)-Jenkins+K8s部署详细步骤

​ 1、整体部署架构图 2、编写脚本 vi pipeline.yml apiVersion: apps/v1 kind: Deployment metadata:namespace: testname: pipelinelabels:app: pipeline spec:replicas: 2selector:matchLabels:app: pipelinetemplate:metadata:labels:app: pipelinespec:containers:- nam…

深入了解鸿鹄电子招投标系统:Java版企业电子招标采购系统的核心功能

随着市场竞争的加剧和企业规模的扩大&#xff0c;招采管理逐渐成为企业核心竞争力的重要组成部分。为了提高招采工作的效率和质量&#xff0c;我们提出了一种基于电子化平台的解决方案。该方案旨在通过电子化招投标&#xff0c;使得招标采购的质量更高、速度更快&#xff0c;同…

基于JAVA的数据可视化的智慧河南大屏 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 数据模块 A4.2 数据模块 B4.3 数据模块 C4.4 数据模块 D4.5 数据模块 E 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的数据可视化的智慧河南大屏&#xff0c;包含了GDP、…

iOS 调试工具CocoaDebug

1、使用pod工具在项目里面添加CocoaDebug的SDK。 platform :ios, 11.0target ShopService doproject ShopServiceuse_frameworks!pod CocoaDebug, :configurations > [Debug]end2、之后就可以在项目里面看到效果了 APP上显示的是一个黑色背景的小圆圈。 上面39表示调用了39…

使用 vue-json-viewer 工具在界面显示json格式数据

安装vue-json-viewer npm install vue-json-viewer --save 引入&#xff1a; import JsonViewer from vue-json-viewer Vue.use(JsonViewer) 使用&#xff1a; <json-viewer :value"jsonData" show-double-quotes :preview-mode"true" :show-array…

three.js 使用 tweenjs绘制相机运动动画

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div class"box-right"…

数据交付变革:研发到产运自助化的转型之路

作者 | Chris 导读 本文讲述为了提升产运侧数据观察、分析、决策的效率&#xff0c;支持业务的快速迭代&#xff0c;移动生态数据研发部对数仓建模与BI工具完成升级&#xff0c;采用宽表建模与TDA平台相结合的方案&#xff0c;一站式自助解决数据应用需求。在此过程中&#xff…

黑帽SEO简介

什么是黑帽 SEO&#xff1f; 黑帽SEO是一种违反搜索引擎指南的做法&#xff0c;用于使网站在搜索结果中排名更高。这些不道德的策略并不能解决搜索者的问题&#xff0c;并且通常以搜索引擎的惩罚而告终。黑帽技术包括关键字填充、伪装和使用专用链接网络。 出现在搜索结果中对…

vue2-手写轮播图

轮播图5长展示&#xff0c;点击指示器向右移动一个图片&#xff0c;每隔2秒移动一张照片&#xff01; <template><div class"top-app"><div class"carousel-container"><div class"carousel" ref"carousel">&…