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

news/2024/11/23 2:06:42/

单例模式

 

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

  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.ppmy.cn/news/91659.html

相关文章

基于混合蛙跳的路径规划算法

路径规划算法&#xff1a;基于混合蛙跳优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于混合蛙跳优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

数据库的简介

文章目录 前言一、为什么需要数据库二、数据库基本概念1.什么是数据库2.什么是数据库管理系统3.数据库表4.数据库表 三、常见的数据库管理系统 前言 数据库的简介 一、为什么需要数据库 信息时代数据容量海量增长&#xff0c;结构化存储大量数据&#xff0c;便于高效的检索和…

Transformer应用之构建聊天机器人(二)

四、模型训练解析 在PyTorch提供的“Chatbot Tutorial”中&#xff0c;关于训练提到了2个小技巧&#xff1a; 使用”teacher forcing”模式&#xff0c;通过设置参数“teacher_forcing_ratio”来决定是否需要使用当前标签词汇来作为decoder的下一个输入&#xff0c;而不是把d…

调用华为API实现图像搜索

调用华为API实现图像搜索 1、作者介绍2、华为API介绍2.1 华为云图像搜索2.2 图像搜索应用场景2.2.1商品图片搜索2.2.2版权图片搜索 2.3 调用华为API实现图像标签 3、实验过程3.1完整代码3.2运行结果3.3常见错误 1、作者介绍 张勇进&#xff0c;男&#xff0c;西安工程大学电子…

计算机组成原理-指令系统-指令格式及寻址方式

目录 一、指令的定义 1.1 扩展操作码指令格式 二、指令寻址方式 2.1 顺序寻址 2.2 跳跃寻址 三、 数据寻址 3.1 直接寻址 3.2 间接寻址 3.3 寄存器寻址 ​ 3.4 寄存器间接寻址 3.5 隐含寻址 3.6 立即寻址 3.7 偏移地址 3.7.1 基址寻址 3.7.2 变址寻址 3.7.3 相对寻址…

大数据框架-Hadoop

大数据框架-Hadoop 1.什么是大数据 大数据是指由传统数据处理工具难以处理的规模极大、结构复杂或速度极快的数据集合。这些数据集合通常需要使用先进的计算和分析技术才能够处理和分析&#xff0c;因此大数据技术包括了大数据存储、大数据处理和大数据分析等方面的技术和工具…

Elasticsearch扫盲篇

1. 什么是搜索&#xff1f; 在日常的工作和学习中&#xff0c;当我们说想找查询任何的信息的时候&#xff0c;可能第一时间会想到上百度或者谷歌去搜索一下。比如说找一部自己喜欢的电影&#xff0c;或者说找一本喜欢的书&#xff0c;或者找一条感兴趣的新闻。但是百度和谷歌不…

【前端面试知识点】- 大厂面试(三)

目录 1.JS垃圾回收机制2.form表单的使用以及相应的属性值3.vue中的双向数据绑定原理&#xff08;重点深入学习&#xff09;4.vue单向数据流5.undefined、null、NaN有什么区别&#xff1f;7.如何获取安全的undefined 值&#xff1f;8.Object.is() 与比较操作符 “ ” 、 “” 的…