组合和聚合

不是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.hqwc.cn/news/342846.html

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

相关文章

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

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

linux下can调试工具canutils编译安装

命令安装只需要 sudo apt-get install canutils 一、下载源码 下载canutils和libsocketcan libsocketcan地址&#xff1a;https://public.pengutronix.de/software/libsocketcan/libsocketcan-0.0.11.tar.bz2 #0.0.11版本 canutils地址&#xff1a;https://public.pengutronix…

ERA5合集,使用ERA5得到GNSS站点的温度,气压,水汽压,Tm和PWV合集,可以求五个参数

0. 码字不易&#xff0c;点赞加关注&#xff08;公众号&#xff1a;WZZHHH&#xff0c;部分资料在公众号可以下载&#xff09;&#xff0c;使用请注明出处&#xff08;根据我的研究方向&#xff0c;我会不断更新代码&#xff09;。 1.计算PWV的方法一般采用有三种&#xff0c; …

【源码阅读】事件订阅包v2

1、Feed Feed 实现一对多订阅&#xff0c;其中事件的载体是通道。发送到 Feed 的值会同时传送到所有订阅的通道。 与Typemux的对比 链接: link TypeMux是一个同步的事件框架&#xff0c;当有一个被订阅的事件发生的时候&#xff0c;会遍历该事件对应的订阅者通道&#xff0c;…

详解动态网页数据获取以及浏览器数据和网络数据交互流程-Python

前言 动态网页是一种在用户浏览时实时生成或变化的网页。与静态网页不同&#xff0c;后者通常是预先编写好的HTML文件&#xff0c;直接由服务器传送给浏览器&#xff0c;内容在服务端生成且固定不变&#xff0c;获取静态数据的文章课查阅博主上一篇文章&#xff1a;详解静态网…

SSL证书影响网站SEO

SSL证书对网站SEO&#xff08;搜索引擎优化&#xff09;有一些积极的影响。搜索引擎公司&#xff0c;如Google&#xff0c;已经明确表示安全性是他们排名算法的一个因素。 1. 搜索引擎排名优势&#xff1a;Google在其搜索算法中考虑了网站的安全性作为排名的一个信号。使用SSL…

基于 TensorFlow.js 构建垃圾评论检测系统

基于 TensorFlow.js 构建垃圾评论检测系统。 准备工作 在过去的十年中,Web 应用变得越来越具有社交性和互动性,而即使是在中等热门的网站上,也有数万人可能实时对多媒体、评论等的支持。这也让垃圾内容发布者有机会滥用此类系统,将不太令人满意的内容与其他人撰写的文章、视…

MySQL-索引回顾

索引是面试高频问答题&#xff0c;参考百度/CSDN/尚硅谷/黑马程序员/阿里云开发者社区&#xff0c;决定将索引知识回顾一下&#xff0c;忘记时&#xff0c;点开即可&#xff0c;时刻保持更新&#xff0c;事不宜迟&#xff0c;即刻享用。 索引概述 索引&#xff08;index&#…

phpinfo和php -m 加载的php.ini不一致

目的&#xff1a; 将phpinfo在web中展示的php.ini和在命令行中展示的php.ini加载路径设置一致。 原本的php.ini加载路劲是&#xff1a; /usr/local/lib/php.ini 解决思路&#xff1a; &#xff08;1&#xff09;which php 查看服务器加载的php的位置&#xff0c;这里原来是&a…

python-os模块学习,全

目前&#xff0c;计算机上主流的操作系统有Windows、Unix、Mac OS等&#xff0c;os模块为多操作系统的访问提供了相关功能的支持&#xff0c;涉及对文件相关操作功能的实现&#xff0c;系统访问path路径的操作&#xff0c;shell命令行操作&#xff0c;Linux扩展属性的操作&…

井盖异动传感器,守护脚下安全

随着城市化进程的加速&#xff0c;城市基础设施的安全问题日益受到关注。其中&#xff0c;井盖作为城市地下管道的重要入口&#xff0c;其安全问题不容忽视。然而&#xff0c;传统的井盖监控方式往往存在盲区&#xff0c;无法及时发现井盖的异常移动。为此&#xff0c;我们推出…

[JAVA数据结构] 认识 Iterable、Collection、List 的常见方法签名以及含义

目录 (一)Iterable 1. 介绍 2. 常见方法 (二)Collection 1. 介绍 2. 常见方法 (三) List 1. 介绍 2. 常见方法 总结 (一) Iterable 1. 介绍 Iterable接口是Java中的一个接口&#xff0c;它是集合框架中的根接口之一。Iterable接口表示实现了迭代功能&#xff0c;即可以通过迭…