14-C++面向对象(单例模式、const成员、浅拷贝、深拷贝)

news2024/11/26 23:28:05

单例模式

 

        单例模式:设计模式的一种,保证某个类永远只创建一个对象

  1.         构造函数\析构函数 私有化
  2.         定义一个私有的static成员变量指向唯一的那个单例对象(Rocket* m_rocket)
  3.         提供一个公共的访问单例对象的接口(shareRocket())

class Rocket {
private:
	static Rocket* m_rocket;
	Rocket() {}
public:
	static Rocket* shareRocket() {
		//注意考虑多线程安全问题
		if (m_rocket==NULL)
		{
			m_rocket = new Rocket();
		}
		return m_rocket;
	}
	void run() {
		cout << "run()" << endl;
	}
};
Rocket* Rocket::m_rocket = NULL;
int main() {
	Rocket* p = Rocket::shareRocket();
	Rocket* p1 = Rocket::shareRocket();
	Rocket* p2 = Rocket::shareRocket();
	Rocket* p3 = Rocket::shareRocket();
	cout << p << endl;
	cout << p1 << endl;
	cout << p2 << endl;
	cout << p3 << endl;
	p->run();
	return 0;
}

当你需要销毁掉堆里的单例对象时,也需要在类中写一个公共接口

static void deleteRocket() {
        //需要考虑多线程问题
		if (m_rocket != NULL)
		{
			delete m_rocket;
			m_rocket = NULL;//不赋值NULL可以会成野指针。使得重新申请单例对象时出现错误                     
                            //if(m_rocket==NULL)会不成立
		}
	}

为了防止外部直接delete p;而不去通过接口deleteRocket()删除,推荐把析构函数也私有化,完整代码如下:

#include<iostream>
using namespace std; 
/*
单例模式:设计模式的一种,保证某个类永远只创建一个对象
1、构造函数\析构函数私有化
2、定义一个私有的static成员变量指向唯一的那个单例对象
3、提供一个公共的访问单例对象的接口
*/

class Rocket {
private:
	static Rocket* m_rocket;
	Rocket() {}
	~Rocket(){}
public:
	static Rocket* shareRocket() {
		//注意考虑多线程安全问题
		if (m_rocket==NULL)
		{
			m_rocket = new Rocket();
		}
		return m_rocket;
	}
	static void deleteRocket() {
		if (m_rocket != NULL)
		{
			delete m_rocket;
			m_rocket = NULL;
		}
	}
	void run() {
		cout << "run()" << endl;
	}
};
Rocket* Rocket::m_rocket = NULL;
int main() {
	Rocket* p = Rocket::shareRocket();
	Rocket* p1 = Rocket::shareRocket();
	Rocket* p2 = Rocket::shareRocket();
	Rocket* p3 = Rocket::shareRocket();
	cout << p << endl;
	cout << p1 << endl;
	cout << p2 << endl;
	cout << p3 << endl;
	p->run();
	Rocket::deleteRocket();
	return 0;
}

const成员

  const成员:被const修饰的成员变量、非静态成员函数

const成员变量

  1. 必须初始化(类内部初始化),可以在声明的时候直接初始化赋值
  2. 非static的const成员变量还可以在初始化列表冲初始化

const成员函数

  1. const关键字写在参数列表后面,函数的声明和实现都必须带const
  2. 内部不能修改非static成员变量
  3. 内部只能调用const成员函数、static成员函数
  4. 非const成员函数可以调用const成员函数
#include <iostream>
using namespace std;

class Car
{
	int m_price;
	void run() const {
		cout << "run()" << endl;
		m_price = 0;//error
	}
};
int main() {

	return 0;
}

 引用类型成员

  1. 引用类型成员变量必须i初始化(不考虑static情况)
  2. 在声明的时候直接初始化
  3. 通过初始化列表初始化

拷贝构造函数

  1. 拷贝构造函数是构造函数的一种
  2. 当利用已存在的对象创建一个新对象是(类似于拷贝),就会调用新对象的拷贝函数进行初始化
#include <iostream>
using namespace std;
class Car {
	int m_price;
	int m_length;
public:
	Car(int price = 0, int length = 0) :m_price(price), m_length(length) {
		cout << "Car(int price = 0, int length = 0) :m_price(price)" << endl;
	}
	//拷贝构造函数
	Car(const Car& car):m_price(car.m_price),m_length(car.m_length) {
		cout << "const Car& car" << endl;
		}
	void display() {
		cout << "price=" << m_price << ",length=" << m_length << endl;
	}
};


int main() {
	Car car1;
	Car car2(100, 200);
	//拷贝构造函数,利用已经存在的car2对象创建了一个car3对象
	//car3初始化时会调用拷贝构造函数
	Car car3(car2);
	car3.display();

	return 0;
}

浅拷贝、深拷贝

编译器默认的提供的拷贝是浅拷贝(shallow copy)

  1. 将一个对象中所有成员变量的值拷贝到另一个对象
  2. 如果某个成员变量是个指针,只会拷贝指针中存储的地址值,并不会拷贝指针指向的内存空间
  3. 可能会导致堆空间多次free的问题

如果需要实现深拷贝(deep copy),就需要自定义拷贝构造函数

  1. 将指针类型的成员变量所指向的内存空间,拷贝到新的内存空间

下面这个例子是说浅拷贝导致了堆空间的变量指向了栈空间,不安全

#include<iostream>
using namespace std;
class Car {
	int m_price;
	char* m_name;
public:
	Car(int price = 0, char* name = NULL):m_price(price),m_name(name) {}
	void display() {
		cout << "price is " << m_price << ",name is " <<m_name<< endl;
	}
};
int main() {
	const char* name = "bmw";
	char name2[] = { 'b','m','w','\0' };
	cout << name2 << endl;
	cout << strlen(name) << endl;

	Car *car = new Car(100, name2);
	car->display();
	return 0;
}

深拷贝,连同所指向的内存空间也拷贝了

#include<iostream>
using namespace std;
class Car {
	int m_price;
	char* m_name;
public:
	Car(int price = 0, const char* name = NULL) :m_price(price){
		if (name == NULL) return;
		//申请新的堆空间
		m_name = new char[strlen(name) + 1]{};
		//拷贝字符串数据到新的堆空间
		strcpy(m_name, name);
	}
	~Car() {
		if (m_name == NULL) return;
		delete m_name;
		m_name = NULL;
	}
	void display() {
		cout << "price is " << m_price << ",name is " << m_name << endl;
	}
};

int main() {
	const char* name = "bmw";
	char name2[] = { 'b','m','w','\0' };
	cout << name2 << endl;
	cout << strlen(name) << endl;

	Car* car = new Car(100, name);
	car->display();
	return 0;
}

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

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

相关文章

[组合数学] 容斥原理polya定理

数学 A 170 物理 B130 化学C120 A ∩ B 45 A ∩ C 20 B ∩ C 22 A ∩ B ∩ C 3 A\cap B 45\quad A\cap C20 \quad B\cap C 22 \quad A\cap B\cap C 3 A∩B45A∩C20B∩C22A∩B∩C3 ∣ A ∪ B ∪ C ∣ A B C − A ∩ B − B ∩ C − A ∩ C A ∩ B ∩ C 170 130 …

vcruntime140.dll丢失怎么办?怎么解决vcruntime140.dll丢失的问题

当您运行一个需要此文件的程序时&#xff0c;如果您的系统中不存在这个文件&#xff0c;会提示出错信息“找不到vcruntime140.dll”或“vcruntime140.dll丢失”。这种情况下&#xff0c;您需要解决这个问题&#xff0c;才能继续运行此应用程序。我们将介绍vcruntime140.dll丢失…

python基于协同过滤推荐算法的电影观后感推荐管理系统的设计

本课题所设计的影单管理系统&#xff0c;使用B/S架构&#xff0c;Python语言进行开发&#xff0c;它的优点代码不能从浏览器查看&#xff0c;保密性非常好&#xff0c;比其他的影单管理更具安全性。Python还容易修改和调试&#xff0c;毕竟影视是在不断发展过程中&#xff0c;难…

【P34】JMeter ForEach控制器(ForEach Controller)

文章目录 一、ForEach控制器&#xff08;ForEach Controller&#xff09;参数说明二、准备工作三、测试计划设计 一、ForEach控制器&#xff08;ForEach Controller&#xff09;参数说明 可以对一个组变量进行循环迭代&#xff1b;该组件通常与后置处理器中的 JSON 提取器、正…

自动化测试工具——Selenium详解

前言 Selenium是一个用于Web应用程序测试的工具。是一个开源的Web的自动化测试工具&#xff0c;最初是为网站自动化测试而开发的&#xff0c;类型像我们玩游戏用的按键精灵&#xff0c;可以按指定的命令自动操作&#xff0c;不同是Selenium可以直接运行在浏览器上&#xff0c;…

AIBlockChain:“知名博主独家讲授”人工智能创新应用竞赛【精选实战作品】之《基于计算机视觉、自然语言处理、区块链和爬虫技术的智能会议系统》软件系统案例的界面简介、功能介绍分享之二、会中智能

AI&BlockChain&#xff1a;“知名博主独家讲授”人工智能创新应用竞赛【精选实战作品】之《基于计算机视觉、自然语言处理、区块链和爬虫技术的智能会议系统》软件系统案例的界面简介、功能介绍分享之二、会中智能系统 目录 人工智能竞赛【精选实战作品】之《基于计算机视…

【网络编程一】初识网络:IP与端口号 网络模型

目录 &#x1f31f;需要知道 一、基础概念 &#x1f308;1、IP地址与端口号 &#x1f308;2、五元组 二、协议分层 &#x1f308;1、OSI七层网络网络模型 &#x1f308;2、TCP/IP五层(四层)模型 &#x1f308;3、封装和分用&#xff08;重点&#xff01;&#xff09; &…

Kotlin 协程中的并发问题:我明明用 mutex 上锁了,为什么没有用?

前言 最近在接手的某项目中&#xff0c;主管给我发来了一个遗留以久的 BUG&#xff0c;让我看看排查一下&#xff0c;把它修复了。 项目的问题大概是在某项业务中&#xff0c;需要向数据库插入数据&#xff0c;而且需要保证同种类型的数据只被插入一次&#xff0c;但是现在却…

每日一练 | 网络工程师软考真题 Day13

阅读以下说明&#xff0c;回答以下问题1至问题6。 【说明】 某公司的两个部门均采用Windows 2003的NAT功能共享宽带连接访问Internet&#xff0c;其网络结构和相关参数如图2-1所示。ISP为该公司分配的公网IP地址段为202.117.12.32/29。 【问题1】在Windows 2003中&#xff0c;…

NodeJS Crypto加密⑤

文章目录 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&#x1f618;前言NODE内置模块Zlib模块 createGzip&#xff08;CreateGzip方法 异步&#xff09;Crypto加密模块 getHashes 方法 createHash 方法 createHmac 方法…

野火RA6M5开发板 DHT11温湿度传感器 OLED显示测试学习

野火RA6M5开发板 DHT11温湿度传感器 OLED显示测试学习 DHT11温湿度传感器 DHT11是一款有已校准数字信号输出的温湿度传感器。 精度湿度5%RH&#xff0c; 温度2℃&#xff0c;量程湿度20-90%RH&#xff0c; 温度0~50℃。 更多DHT11信息请参考&#xff1a;https://baike.sogou…

img[:, :, ::-1] 通俗理解

&#x1f468;‍&#x1f4bb;个人简介&#xff1a; 深度学习图像领域工作者 &#x1f389;工作总结链接&#xff1a;https://blog.csdn.net/qq_28949847/article/details/128552785 链接中主要是个人工作的总结&#xff0c;每个链接都是一些常用demo&#xff0c…

Redis5.0+ Redis集群水平扩容|节点删除

文章目录 1. 背景2. Redis集群水平扩展2.1 启动集群2.2 连接其中一个节点2.3 配置新节点2.4 启动新节点2.5 配置8007节点加入集群&#xff0c;成为主节点2.6 增加子节点2.7 分配hash槽2.8 检查 Redis 集群 3. 节点删除4. redis集群命令帮助5. 参考文献 1. 背景 之前搭建了Redi…

硬件系统工程师宝典(26)-----四种BJT应用电路分析

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。上篇我们说到晶体三极管&#xff08;BJT&#xff09;的几种应用电路&#xff1a;三极管的输入端钳制电压电路、BJT电平转换电路、Boost升压电路、图腾…

WGCNA | 不止一个组的WGCNA怎么分析嘞!?~(二)(共识网络分析-第二步-构建网络与模块-Blockwise)

1写在前面 临床工作越来越忙了&#xff0c;更新的频率也开始降低了&#xff0c;希望各位小伙伴可以理解一下。&#x1f62d; 最近看到塞尔达-王国之泪发售了&#xff0c;真的是想买一个&#xff0c;但想想根本没有时间去玩&#xff0c;买回来只能吃灰。&#x1f972; 想问问小伙…

G0第22章 :获取参数、文件上传、重定向、Gin路由、Gin中间件、运行多个服务

05 获取参数 1、获取querystring参数 querystring 指的是URL中的 ? 后面携带的参数&#xff0c;例如&#xff1a; /user/search?username小王子&address天津 。获取请求querystring参数的方法如下&#xff1a; package mainimport ("github.com/gin-gonic/gin&qu…

Git基础笔记(只含常用命令)

1.Git基本概念 1.git三区 工作区 -->git add 暂存区 --> git commit版本区域 暂存区用来存放临时文件&#xff0c;相当于只编辑没有保存 2.文件状态 命令 git status 查看文件状态 大体来说有被版本管理和没被版本管理两种状态 a.txt 执行了git add 3.git本地仓库命令 g…

面试篇:SpringCloud

一、SpringCloud常见的组件有什么&#xff1f; 1、常见微服务功能架构图 2、阿里巴巴SpringCloud常用组件 注册中心/配置中心&#xff1a;Nacos负载均衡&#xff1a;Ribbon服务调用&#xff1a;Feign服务保护&#xff1a;Sentinel服务网关&#xff1a;Gateway 二、服务注册…

阿里云IoT物联网平台

IoT物联网平台 一、工作原理 1、MQTT&#xff08;Message Queuing Telemetry Transport&#xff09; 是一种轻量级的消息传输协议&#xff0c;专门设计用于物联网&#xff08;IoT&#xff09;应用中的通信。它是一种发布/订阅&#xff08;publish/subscribe&#xff09;模式的…

【OpenCV DNN】Flask 视频监控目标检测教程 04

欢迎关注『OpenCV DNN Youcans』系列&#xff0c;持续更新中 【OpenCV DNN】Flask 视频监控目标检测教程 04 3.4 用Flask构建流媒体服务器3.4.1 流媒体服务器基本知识3.4.2 用Flask搭建流媒体服务器 Flask04 完整例程cvFlask04 项目的文件树cvFlask04.pyindex1.html 本系列从零…