当前位置: 首页 > news >正文

特殊类的设计和类型转换

文章目录

  • 特殊类
    • 1.请设计一个类,不能被拷贝
    • 2. 请设计一个类,只能在堆上创建对象
    • 3. 请设计一个类,只能在栈上创建对象 (★)
    • 4. 请设计一个类,不能被继承
    • 5. 请设计一个类,只能创建一个对象(单例模式)
      • 1. 饿汉模式
      • 2. 懒汉模式
  • 类型转换
    • 内置类型转为自定义类型
    • 自定义类型转换为内置类型
    • 自定义类型转为自定义类型
  • 四种强制类型转换操作符
    • 1.static_cast
    • 2.reinterpret_cast
    • 3.const_cast
    • 4.dynamic_cast

特殊类

1.请设计一个类,不能被拷贝

这个很简单,直接把拷贝构造delete就行了,但是我们还需要把赋值运算符重载也delete了,因为在赋值过程的时候需要用到拷贝构造。

//1. 设计一个类,不能别拷贝
class NoCopy
{
public:NoCopy(int x = 0):_x(x){}NoCopy(const NoCopy& cp) = delete;NoCopy& operator=(const NoCopy& cp) = delete;~NoCopy(){cout << "~NoCopy()" << endl;}private:int _x;
};

2. 请设计一个类,只能在堆上创建对象

那么我们创建的变量分为三种情况:

  1. 静态区

那也就是说我们对象都需要 n e w new new出来,那么我们就需要把构造函数delete就可以了。同时每次创建对象都只能 n e w new new出来。

//2. 请设计一个类,只能在堆上创建对象
class HeapOnly
{
public:static HeapOnly* Getobject(int a = 0){return new HeapOnly(a);}HeapOnly(const HeapOnly& hp) = delete;HeapOnly& operator=(const HeapOnly& hp) = delete;~HeapOnly(){delete this;}
private:HeapOnly(int a = 0) //构造函数变为私有那么外层无法使用,每次创建对象只能调用Getobject来创建。:_a(a){}int _a;
};

还有一种思路是把析构函数设置为私有,但是这种情况就需要手动释放资源了。

//2. 请设计一个类,只能在堆上创建对象
class HeapOnly
{
public:static HeapOnly* Getobject(int a = 0){return new HeapOnly(a);}HeapOnly(int a = 0):_a(a){}HeapOnly(const HeapOnly& hp) = delete;HeapOnly& operator=(const HeapOnly& hp) = delete;void Destory(){delete this;}
private:~HeapOnly(){cout << "~HeapOnly()" << endl;}int _a;
};

3. 请设计一个类,只能在栈上创建对象 (★)

//3. 请设计一个类,只能在栈上创建对象
class StackOnly
{
public:static StackOnly Getobject(int a = 0){return StackOnly(a);}~StackOnly(){cout << "~StackOnly()" << endl;}void* operator new(size_t size) = delete;void operator delete(void* p) = delete;
private:StackOnly(int a = 0):_a(a){}int _a;
};void Test_StackOnly()
{StackOnly s1 = StackOnly::Getobject(1); //由于我们需要赋值给s1,所以这里我们不得不把拷贝构造放出来StackOnly* s2 = new StackOnly(s1);//但是这样的情况不能避免,所以此时我们只能从new下手
}

由于new的本质为:构造函数 + operator new

delete的本质为: operator delete + 析构函数

虽然operator new和operator delete为全局函数,但是当局部写了的时候,优先使用局部的。所以这里我们只需要把operator new和operator delete取消即可。

4. 请设计一个类,不能被继承

这里有两种方法:

  1. 把基类的构造私有化,子类调不到父类的构造函数
  2. 直接使用final关键字。

5. 请设计一个类,只能创建一个对象(单例模式)

单例模式:

**一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。**比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。

单例模式有两种实现模式 :

1. 饿汉模式

就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象。

class Singleton
{
public:static Singleton& Getobject(int a = 0){_ins._a = a;return _ins;}Singleton(const Singleton& sl) = delete;Singleton& operator=(const Singleton& sl) = delete;void Print(){cout << _a << endl;cout << _id << endl;cout << _pos << endl;}~Singleton(){cout << "~Singleton()" << endl;}private:static Singleton _ins;Singleton(int a = 0):_a(a){cout << "Singleton()" << endl;}int _a = 0;string _id = "111111111";int _pos = 100;
};
Singleton Singleton::_ins; //在程序初始化之前创建一个对象int main()
{Singleton::Getobject(1).Print(); return 0;
}

2. 懒汉模式

懒汉模式和饿汉模式的区别就在于,饿汉模式是提前初始化好了,而懒汉模式则是调用的时候再初始化。

class Singleton
{
public:static Singleton& Getobject(int a = 0){static Singleton _ins; //调用的时候才初始化_ins._a = a;return _ins;}Singleton(const Singleton& sl) = delete;Singleton& operator=(const Singleton& sl) = delete;void Print(){cout << _a << endl;cout << _id << endl;cout << _pos << endl;}~Singleton(){cout << "~Singleton()" << endl;}private:Singleton(int a = 0):_a(a){cout << "Singleton()" << endl;}int _a = 0;string _id = "111111111";int _pos = 100;
};
int main()
{Singleton::Getobject(1).Print(); return 0;
}

类型转换

在C语言阶段我们学了隐式类型转换和显示类型转换。

//内置类型
int main()
{//隐式类型转换int x = 1;double d = 2.2;x = d;//显示类型转换int* p = (int*)x;cout << x << p << endl;return 0;
}

而在C++中我们还有自定义类型,那么自定义类型和内置类型究竟是怎么转化的呢?

内置类型转为自定义类型

利用自定义类型的构造函数,这个其实在类和对象我们已经学过了,隐式类型转换。

class A
{
public:A(int a = 0):_a(a),_b(a){}A(int a,int b):_a(a),_b(b){}void Print(){cout << _a << " " << _b << endl;}
private:int _a;int _b;
};
int main()
{A a1 = 1;A a2 = { 1,2 };a1.Print();a2.Print();return 0;
}

如上段代码,我们通过自定义类型的构造函数,让内置类型转换为自定以类型。

自定义类型转换为内置类型

重载operator(),但是由于operator()已经被占用,所以为了和别的operator()区分出来,我们需要如下定义:

operator int() //注意这里的int不能写为返回值,只能写在operator后面。
{return _a + _b;
}
int main()
{A a1(1);A a2{ 1,2 };a1.Print();a2.Print();int x = a1;int y = a2;cout << x << " " << y << endl;return 0;
}

自定义类型转为自定义类型

通过构造函数建立关联,两个不同的自定义类型强转是行不通的,所以得去写函数来建立两个类型之间的关系。

class B
{
public:B(int a = 0):_a(a){}operator int() const{return _a;}~B(){cout << "~B()" << endl;}int get() const{return _a;}
private:int _a;
};
class A
{
public:A(int a = 0):_a(a),_b(a){}A(int a,int b):_a(a),_b(b){}A(const B& bb) //直接这里的get()究竟返回的是什么由自己决定。:_a(bb.get()),_b(bb.get()){}void Print(){cout << _a << " " << _b << endl;}operator int() const{return _a + _b;}~A(){cout << "~A()" << endl;}
private:int _a;int _b;
};

再来看如下代码:

int main()
{//自己模拟实现的listbit::list<int> k = { 1,2,3,4 };//这里我们的k.begin()为普通的iteratorbit::list<int>::const_iterator it = k.begin(); //const_iterator = iteratorwhile (it !- k.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

在这里插入图片描述

如上图:
由于我们的迭代器是由我们自己写的模版,那么他们的模版参数并不相同那么实例化出来的类型也不相同,所以这里也属于自定义类型转换自定义类型但由于我们迭代器并没有把两种关联起来,所以这里也是转换不了的 。但是库里面上面代码确可以运行,那几句说明我们库中是实现了iterator->const_iterator的转换的。

	//添加一个构造函数,进来的参数为普通的迭代器	,同时类型转化会产生临时对象,所以要用const修饰,//这样无论我们是普通迭代器还是const_iterator,虽然参数是普通迭代器,但是返回的却是按照对应类型返回。ListIteraotr(const ListIteraotr<T,T&,T*>& ls) :_node(ls._node){}

四种强制类型转换操作符

标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符。

1.static_cast

static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用
static_cast,但它不能用于两个不相关的类型进行转换

int main()
{double d = 12.34;int a = static_cast<int>(d);cout<<a<<endl;return 0;
}

2.reinterpret_cast

reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型

int main()
{//对应隐式类型转换,数据的意义没有改变,值传递double d = 12.34;int a = static_cast<int>(d);cout << a << endl;//对应强制类型转换,数据的意义改变,int -> int*int *p = reinterpret_cast<int*>(a);return 0;
}

3.const_cast

const_cast最常用的用途就是删除变量的const属性,方便赋值

void Test()
{//对应强制类型转换中有风险的去调const属性const int a = 2;int* p = const_cast<int*>(&a);*p = 3;cout << a << endl;cout << *p << endl;
}int main()
{Test();return 0;
}

在这里插入图片描述

但是此时我们发现为什么我们的a还是2呢?原因是编译器进行了优化,虽然内存当中我们a的值已经发生了改变,但是由于我们的a是const修饰的,为常变量,所以编译器会把它直接替换为2或者存入一个寄存器当中,所以并没有去内存当中去取。

4.dynamic_cast

继承体系中:

**向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则) **

向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)

注意这里是引用或者指针,如果是对象的话不可以进行强制类型转换。

在继承体系中,如果我们想要把子类的指针或者引用转化为父类的指针或者引用,会进行一个切片的操作,就是把子类中父类的部分传过去,所以不会产生临时变量。

class A
{
public:virtual void f() {}int _a = 0;
};
class B : public A
{
public:int _b = 0;
};
void fun(A* pa)
{// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回B* pb1 = (B*)pa;B* pb2 = dynamic_cast<B*>(pa);cout << "pb1:" << pb1 << endl;cout << "pb2:" << pb2 << endl;cout << pb1->_a << endl;cout << pb1->_b << endl;
}
int main()
{A a;B b;fun(&a);cout << endl;fun(&b);return 0;
}

如上图,虽然我们static_cast也可以转换,但是并没有dynamic_cast安全,这时为什么呢?

在这里插入图片描述

如上图,当我们调用的是子类的指针,那么我们强转之后是没有问题的,但如果是父类的指针,强转之后我们并没有对应的子类的值啊,所以当我们想要访问的时候必然会出现报错,因为访问了一个根本没有的值。

而dynamic_cast会先判断,如果我们传入的是父类指针,会返回空指针。

如果是子类的会会进行特殊处理,把子类中父类的部分切片进行传递

相关文章:

特殊类的设计和类型转换

文章目录 特殊类1.请设计一个类&#xff0c;不能被拷贝2. 请设计一个类&#xff0c;只能在堆上创建对象3. 请设计一个类&#xff0c;只能在栈上创建对象 &#xff08;★&#xff09;4. 请设计一个类&#xff0c;不能被继承5. 请设计一个类&#xff0c;只能创建一个对象(单例模式…...

ES模块导入、导出学习笔记

ES模块导入、导出学习笔记 1、命名导出、导入1.1、声明时直接导出1.2、先声明&#xff0c;再导出 2、默认导出2.1、声明时直接导出2.2、先声明&#xff0c;再导出 3、命名导出 VS 默认导出3.1、命名导出3.2、默认导出3.3、同时使用 4、使用 as 关键字4.1、在 import 中使用 as4…...

Bagging: 数量,而不是质量。

由 AI 生成&#xff1a;过度简化的树、引导聚合、集成方法、弱学习器、减少方差 集成方法 — 数量&#xff0c;而不是质量 一、说明 机器学习中的集成方法是指组合多个模型以提高预测性能的技术。集成方法背后的基本思想是聚合多个基础模型&#xff08;通常称为弱学习器&#…...

维信小程序禁止截屏/录屏

一、维信小程序禁止截屏/录屏 //录屏截屏,禁用wx.setVisualEffectOnCapture({visualEffect:hidden});wx.setVisualEffectOnCapture(Object object) 测试安卓手机&#xff1a; 用户截屏&#xff0c;被禁用 用户录屏&#xff0c;录制的是空白内容/黑色内容的视频。 二、微信小…...

不同大模型代码解释对比

包含ChatGPT&#xff0c;讯飞星火&#xff0c;通义千问&#xff0c;腾讯元宝&#xff0c;智谱清言。 目标是想让大模型解释一个用于预处理人体骨骼关节三维坐标数据样本进行填补空帧的Python函数。 def f_padding_none(data):s data.copy()# print(pad the null frames with…...

Python函数的编写

函数实现 首先&#xff0c;我们来看一个简单的Python函数&#xff0c;它使用os和os.path模块来遍历当前目录及其所有子目录&#xff0c;并列出所有文件的名称。 import os def list_all_files(startpath): """ 列出指定路径&#xff08;包括其子目录&#xff…...

Linux下的常用命令分享 二(ubuntu 16.04)

1、ls -l的返回值说明 以图中为例&#xff0c;说明对于cc.txt.tar.gz文件&#xff0c;文件拥有者即创建该文件的人可以对该文件进行读写操作&#xff0c;但不能执行该文件&#xff0c;文件组成员用户可以进行读写操作&#xff0c;但不能执行该文件&#xff0c;其他用户只可读&…...

FPGA随记——OSERDESE2和IERDESE2

http://t.csdnimg.cn/yNvxf---看这个篇吧 这个挺好的 OSERDESE2 模块要求复位信号高电平有效&#xff0c;并且 需要将异步复位信号同步到串行时钟域。 除了用原语调用&#xff0c;还可以用High Speed SelectIO Wizard这个IP 进行调用 针对具体select IO这个IP的使用和介绍&…...

Xmind思维导图领衔,三款常备神器助你2024年思维升级!

到了2024年&#xff0c;信息多得让人眼花&#xff0c;新东西学都学不完。要在这么多信息里保持清醒&#xff0c;快速学东西&#xff0c;对大家来说是个考验。好在&#xff0c;科技帮了我们大忙&#xff0c;比如思维导图软件&#xff0c;它们直观又灵活&#xff0c;帮我们提高思…...

SEO服务值得吗?提升销售和营销策略的5种方法

在不久之前&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;通常被视为一个独立的实体&#xff0c;企业把提升排名和推动自然流量作为重点。随后&#xff0c;AI登场了&#xff0c;让每个人都忙于弄清“游戏”的新规则&#xff0c;一些公司因此质疑SEO服务是否值得。答案是…...

传统CV算法——角点特征点提取匹配算法实战

harris角点 角点可以是两个边缘的角点&#xff1b;角点是邻域内具有两个主方向的特征点&#xff1b;角点通常被定义为两条边的交点&#xff0c;更严格的说&#xff0c;角点的局部邻域应该具有两个不同区域的不同方向的边界。或者说&#xff0c;角点就是多条轮廓线之间的交点。…...

小米电视使用adb 卸载自带应用教程

小米电视使用ADB&#xff08;Android Debug Bridge&#xff09;卸载自带应用的教程如下。请注意&#xff0c;在操作过程中请确保谨慎行事&#xff0c;避免误删系统关键应用导致电视无法正常使用。 准备工作 下载ADB工具&#xff1a; 在电脑上下载ADB工具。ADB是Android Debug …...

编译FFmpeg动态库

编译FFmpeg动态库 环境 macOS High SierraFFmpeg 4.3android-ndk-r21b 编译so库 下载FFmpeg4.3源代码&#xff0c;进入源码目录创建build_android.sh脚本&#xff0c;ffmpeg从4.0起新增了target-osandroid&#xff0c;所以不用再修改configure文件。 注意&#xff1a; ndk…...

yum的基本使用方法

yum&#xff08;全称 "Yellow dog Updater Modified"&#xff09;是基于RPM包管理器的软件包管理系统&#xff0c;主要用于Fedora和Red Hat系列的Linux发行版中。它允许用户安装、更新、删除以及搜索软件包&#xff0c;并能自动处理软件包之间的依赖关系。下面是一些…...

Nginx+Keepalive集群实战

随着Nginx在国内的发展潮流&#xff0c;越来越多的互联网公司都在使用Nginx&#xff0c;Nginx高性能、稳定性成为IT人士青睐的HTTP和反向代理服务器。 Nginx负载均衡一般位于整个网站架构的最前端或者中间层&#xff0c;如果为最前端时单台Nginx会存在单点故障&#xff0c;也就…...

[数据集][目标检测]街道乱放广告牌检测数据集VOC+YOLO格式114张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;114 标注数量(xml文件个数)&#xff1a;114 标注数量(txt文件个数)&#xff1a;114 标注类别…...

腾讯云的免费ssl证书过期后不占用免费额度

我申请了三张免费证书&#xff0c;两张过期了&#xff0c;已使用的数量还是1&#xff0c;说明已过期的不占免费额度&#xff0c;这样的话&#xff0c;只要每三个月重新申请就能一直用免费证书了。 下证很快&#xff0c;第一张一分钟以内&#xff0c;第二张大概5分钟左右。 原来…...

MySQL学习(DDL,DML,DQL)基本语法总结

DDL 使用某个数据库 use world;展示表 show tables;创建表 create table student(id int,name varchar(10),age int,gender varchar(10));删除表 drop table student; 修改表结构 查看表结构 desc student;添加列 alter table student add dept varchar(10);修改列名和类型…...

JAVA学习-练习试用Java实现“单词反转”

问题&#xff1a; 随便输出一个字符串 String str "45abc,defg"; 里面含有 abc&#xff0c;de&#xff0c;fg 三个单词 怎么处理能让单词反转&#xff0c;其他顺序不变呢 输出 “45cba,edgf”; 解答思路&#xff1a; 以下是使用 Java 实现的单词反转程序&#xff1a…...

【MySQL】深圳大学数据库实验一

目录 一、实验目的 二、实验要求 三、实验设备 四、建议的实验步骤 4.1 使用SQL语句创建如上两张关系表 4.2 EXERCISES. 1 SIMPLE COMMANDS 4.3 EXERCISES 2 JOINS 4.4 EXERCISES 3 FUNCTIONS 4.5 EXERCISES 4 DATES 五、实验总结 5.1 数据库定义语言&#xff08;DDL…...

DS18B20寄生供电模式全解析:3.3V系统下的STM32省电测温方案

DS18B20寄生供电模式全解析&#xff1a;3.3V系统下的STM32省电测温方案 在物联网设备开发中&#xff0c;低功耗设计往往决定着产品的成败。当我们需要在电池供电环境下实现长时间温度监测时&#xff0c;DS18B20传感器的寄生供电模式配合STM32的3.3V系统&#xff0c;能为我们带来…...

Wux Weapp 性能优化终极指南:如何减少包体积提升加载速度

Wux Weapp 性能优化终极指南&#xff1a;如何减少包体积提升加载速度 【免费下载链接】wux-weapp :dog: 一套组件化、可复用、易扩展的微信小程序 UI 组件库 项目地址: https://gitcode.com/gh_mirrors/wu/wux-weapp Wux Weapp 是一套组件化、可复用、易扩展的微信小程序…...

从Vue 2老项目平滑升级到Vue 3,我踩过的坑和最佳迁移路径总结

从Vue 2老项目平滑升级到Vue 3&#xff0c;我踩过的坑和最佳迁移路径总结 去年接手了一个运行三年的电商后台系统&#xff0c;技术栈停留在Vue 2.6 Vuex Webpack的组合。随着业务复杂度提升&#xff0c;性能瓶颈和开发效率问题日益凸显。经过三个月渐进式迁移&#xff0c;最终…...

CUAV Pixhawk V6X飞行控制器5大核心技术深度解析与实战部署指南

CUAV Pixhawk V6X飞行控制器5大核心技术深度解析与实战部署指南 【免费下载链接】PX4-Autopilot PX4 Autopilot Software 项目地址: https://gitcode.com/gh_mirrors/px/PX4-Autopilot CUAV Pixhawk V6X作为PX4生态系统的旗舰级飞行控制器&#xff0c;基于Pixhawk Autop…...

Arduino-Pico终极安装教程:从Arduino IDE到PlatformIO的完整配置

Arduino-Pico终极安装教程&#xff1a;从Arduino IDE到PlatformIO的完整配置 【免费下载链接】arduino-pico Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards 项目地址: https://gitcode.com/gh_mirrors/ar/arduino-pico Arduino-Pico是一款针对Rasp…...

PCD231 B101

ABB PCD231 B101 控制器是 ABB 公司生产的一款高性能励磁控制器模块&#xff0c;专为同步发电机和异步发电机的励磁系统设计&#xff0c;属于 ABB PCD 系列励磁控制器模块的一员。以下是关于该控制器的详细介绍&#xff1a;一、核心功能励磁控制&#xff1a;通过精确控制励磁机…...

高效获取B站视频资源:DownKyi本地缓存与多媒体处理全攻略

高效获取B站视频资源&#xff1a;DownKyi本地缓存与多媒体处理全攻略 【免费下载链接】downkyi 哔哩下载姬downkyi&#xff0c;哔哩哔哩网站视频下载工具&#xff0c;支持批量下载&#xff0c;支持8K、HDR、杜比视界&#xff0c;提供工具箱&#xff08;音视频提取、去水印等&am…...

pd.concat()函数sort与ignore_index参数实战解析:从混淆到精通

1. 为什么pd.concat()的sort参数总让人困惑&#xff1f; 第一次使用pd.concat()函数时&#xff0c;很多人都会被sort参数搞得晕头转向。明明设置了sortTrue和False&#xff0c;怎么结果看起来一模一样&#xff1f;这其实和DataFrame的列顺序以及pandas的设计哲学有关。 让我们先…...

fish-speech-1.5快速上手:WebUI界面操作,简单三步生成语音

fish-speech-1.5快速上手&#xff1a;WebUI界面操作&#xff0c;简单三步生成语音 1. 认识fish-speech-1.5语音合成模型 fish-speech-1.5是一款基于xinference(2.0.0)部署的高质量文本转语音(TTS)模型。它经过超过100万小时的多语言音频数据训练&#xff0c;能够生成自然流畅…...

SEO_解读最新搜索引擎算法,调整你的SEO策略

SEO:解读最新搜索引擎算法&#xff0c;调整你的SEO策略 在当今数字营销的世界里&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;始终是提升网站流量和品牌知名度的关键。每当搜索引擎更新其算法&#xff0c;SEO策略就需要相应调整。今天我们将深入解读最新的搜索引擎算法…...