c++学习之特殊类设计与类型转换

1.设计一个类,无法被拷贝。

方法:c++98,通过私有且只申明不实现拷贝构造与赋值函数,从而实现该类不能被拷贝。c++11引入关键字delete后,可以使构造构造与赋值函数等于delete。效果也是无法被拷贝。

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

方法一,析构私有化

//实现一个类,智能在堆上创建对象
class HeapCreat
{
public:HeapCreat(){cout << "调用构造" << endl;}void release(){delete this;}
private://方法一 析构函数私有化   ~HeapCreat(){cout << "调用析构" << endl;}

方法二,构造私有化

class HeapCreat
{
public:~HeapCreat(){cout << "调用析构" << endl;}void release(){delete this;}static HeapCreat* Creat(){return new HeapCreat;}//但是要禁用拷贝构造,拷贝出都在栈上,不在堆上HeapCrea(const HeapCrea& p)=delete;private:HeapCreat(){cout << "调用构造" << endl;}//方案二 构造函数私有化
};int main()
{//构造函数私有化,最开始都初始化不了,因此只能在类里初始化,并且申明为全局,之后调用类里的初始化HeapCreat* p = HeapCreat::Creat();p->release();return 0;}

3.设计一个类只能在栈上创建对象。

方法一:

还是构造私有化,但是注意拷贝构造,我们拷贝构造可以new,但拷贝构造不能禁用,因为我们需要调用拷贝构造,故有缺陷

//构造私有化
//还是控制构造函数,在类中实现只能在栈上创建。
class HeapCreat
{
public:~HeapCreat(){cout << "调用析构" << endl;}static HeapCreat Creat(){return  HeapCreat();}HeapCreat( HeapCreat& p)=delete;
private:HeapCreat(){cout << "调用构造" << endl;}
};int main()
{HeapCreat p = HeapCreat::Creat();return 0;
}

方法二,直接不让使用new,申明出new并私有化,或delete.

class HeapCreat
{
public:~HeapCreat(){cout << "调用析构" << endl;}static HeapCreat Creat(){return  HeapCreat();}void* operator new(size_t t) = delete;private://void* operator new(size_t t) HeapCreat(){cout << "调用构造" << endl;}
};

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

同上,构造函数私有化,调不了就无法被继承。

c++11提供了关键字final,可以是这个类不能为继承,即最终类。

 一,何为设计模式

    设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。设计模式代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。就是前人总结下来的一些经验。

设计模式分为三大类:创建型模式、结构型模式和行为型模式。

创建型模式包括工厂方法模式、抽象工厂模式、单例模式、建造者模式和原型模式。结构型模式包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式。行为型模式包括责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。

而创作型中常用的就是我们的单例模式,我们以学习单例模式来了解一下设计模式。

二,单例模式

所谓的单例模式其实本质上就是一个特殊类的设计。对于单例模式,在整个进程中,在整个全局环境中,只有这一个实例化的对象,即单实例,对于这样的类的设计就是单例模式。对于大一点的项目,内存池等都会用到单例模式。

那么如是设计出全局下只有一个实例化对象?参考前面的博客,http://t.csdnimg.cn/bA37O,特殊类的设计,那么要想只能实例化出一个对象,且是在全局的环境下,首先,我们要控制构造函数,让其私有化,这样在外面就无法实例化,对于构造提供了两种方式,也就是单例模式的两种模式。

其次就是要求在全局环境下的对象,直接在全局下创建首先无法实例化,构造函数已经私有化了,

且全局的对象是存在弊端的:对象是容易被修改的,多线程下会出现链接问题等。

之后了我们在类里创建对象,但直接创建显然不可行,自己创建自己,但是当我们使用ststic时,就不是自己创建自己,该对象是在静态区中。

因此最终我们选用静态全局的方式实现单例模式。

饿汉模式

顾名思义,该模式很“饥饿”,我们在进入主程序前,就要把这个特殊类设计好给我,也就是在此之前,把对象给我来用。

class TEST
{
public://一般我们通过接口Getinstance 来获取这个对象static TEST* GetInstance()  //对象是静态对象{return  &test;}void ADD(const string key, const string val){ dict.insert(make_pair(key, val));}void Print(){for (auto it : dict){cout << it.first << ":" << it.second<<endl;}}
private://首先类的成员一般都是私有的,这里以一个字典为例map <string, string> dict;//私有构造并禁用拷贝与赋值TEST(){}TEST(const TEST& p) = delete;TEST& operator=(const TEST& p) = delete;static TEST test;//声明   在静态区当中
};
//定义
TEST TEST::test;   //定义了一个类的对象testint main()
{//程序启动 饿汉模式TEST::GetInstance()->ADD("冒泡", "排序");//通过GetInstance获取唯一的对象testTEST::GetInstance()->ADD("希尔", "排序");TEST::GetInstance()->Print();return 0;
}

优缺点:

优点:实现简单

缺点:可能导致进程启动 ,如果有两个单例启动具有先后顺序,控制不了饿汉。

懒汉模式

顾名思义,现吃现做,只有当我们需要使用这个对象的时候,我们才提供对象。即第一次使用的时候才创建。

//懒汉模式
class TEST
{
public:static TEST* GetInstance()  {//主程序要调用使用对象了此时我们在创建//这里主要介绍懒汉的思想,实际上这里的代码还存在线程安全问题if (test == nullptr){test = new TEST;}return test;}void ADD(const string key, const string val){ dict.insert(make_pair(key, val));}void Print(){for (auto it : dict){cout << it.first << ":" << it.second<<endl;}}static void Delete(){if (test){delete test;test = nullptr;}}private://这里以一个字典为例map <string, string> dict;~TEST(){delete test;}TEST(){}TEST(const TEST& p) = delete;TEST& operator=(const TEST& p) = delete;static TEST *test;//声明   在静态区当中class gc{public:~gc(){Delete();}};static gc _gc;
};
//定义
TEST* TEST::test=nullptr;  
TEST::gc  TEST::_gc;int main()
{//程序启动 //懒汉模式TEST::GetInstance()->ADD("冒泡", "排序");//通过GetInstance获取唯一的对象testTEST::GetInstance()->ADD("希尔", "排序");TEST::GetInstance()->Print();}

释放的时候,可以使用智能指针来管理这个指针,也可以在搞一个类用来处理析构,在该对象中,只要释放,就会调用里面的类的的析构使得释放指针。

类型转换

c语言中的类型转换

c语言的类型转换分为两种:

1.隐式类型转换  :int i=1;double b=i;

对于能相互转换的类型,可以隐式类型转换。

2.显式类型转换 :  int j=1;doule ret=double(j)/0.1;

有关联性的类型可以强制类型转换。

c++的类型转换

对于c语言的类型转换,c++认为不太规范,因此c++提出了四种强制类型转换的类型,只有这四类的类型才能强转。

C++提供了四种强制类型转换的函数:static_cast、dynamic_cast、const_cast和reinterpret_cast。

下面对这四种转换操作的适用场景分别进行说明:

static_cast(静态转化): 该运算符把 expression 转换为 type 类型,主要用于基本数据类型之间的转换,如把 uint 转换为 int,把 int 转换为 double 等。此外,还可用于类层次结构中,基类和派生类之间指针或引用的转换。

主要用于相近类型的转化(对应c语言的隐式类型转换的类型):

double i = 3.14159265;
int j = static_cast<int> (i) ;

dynamic_cast:(动态转化) 主要用于类层次间的上行转换或下行转换。在进行上行转换时dynamic_cast 和 static_cast 的效果是一样的,但在下行转换时,dynamic_cast 具有类型检查的功能,比 static_cast 更安全。

dynamic_cast 用于将一个父类对象的指针 / 引用转换为子类对象的指针或引用 ( 动态转换 )
对于向下转型(即父类给给子类),强制类型转换理论上对象是不可以的,但指针和引用可以。 但是向下转换,存在越界访问的问题,是不安全的。
因此c++提供了dynamic_cast:
向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)
向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)
注意:
1. dynamic_cast 只能用于父类含有虚函数的类
i 2. dynamic_cast 会先检查是否能转换成功,能成功则转换,不能则返回 0
注意使用dynamic_cast前提是多态。

const_cast:(常态转化) 该运算符用来修改 expression 的 const 或 volatile 属性。

去调const属性,取地址在强转为普通指针类型。

const int a = 10;int* p = const_cast<int*>(&a);*p = 3;

这里的a可能直接放寄存器了,也可能宏定义了。(不再去内存找这个值) 

因此虽然这里&a与p的地址一样,但是值不一样。利用关键字volatile使得强制去内存取值,我们就会发现两个值是一样的。其次在打印&a时,注意用printf,c++中的cout的输出流在打印时没有对应的函数。

reinterpret_cast: (重新诠释转化)该运算符可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。这个转换是“最不安全”的,不推荐使用

有一定关联,但是意义不相似的类型之间的转换

int a = 1;int* ptr = reinterpret_cast<int*> (a);

注意:类型转换中间会产生临时变量,二临时变量具有常性,是不能被修改的(引用)。

RTTI(了解)

RTTI Run-time Type identification 的简称,即:运行时类型识别。
C++ 通过以下方式来支持 RTTI
1. typeid 运算符
2. dynamic_cast 运算符
3. decltype

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

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

相关文章

提升开发效率的google插件

在如今的软件开发领域&#xff0c;Google Chrome浏览器的开发者插件扮演着至关重要的角色&#xff0c;为开发人员提供了丰富的工具和功能&#xff0c;从而提高了开发效率。下面介绍几款强大的 Google 插件&#xff0c;它们在不同方面为开发者提供了便利&#xff0c;并能显著提升…

pyhton推理代码跨平台部署

一. 场景说明 我们经常训练好的模型需要部署&#xff0c;有时候算法组和工程组是分开的&#xff0c;这时候就需要我们提供C的前后处理逻辑&#xff0c;这时怎么调试我们的C代码呢&#xff1f; 解决方法&#xff1a;把模型推理的结果保存成C可加载的形式&#xff0c;即可调试C…

c++ http第一个服务

c http第一个服务 一、下载相关依赖&#xff1a;这是一个git开源项目 代码仓地址 二、演示代码&#xff0c;编译参数&#xff1a;g test.cpp -I/**** -lpthread #include <httplib.h> using namespace httplib;void wuhan(const Request &req, Response &res) …

MSVS C# Matlab的混合编程系列1 - 看似简单的问题引出

前言&#xff1a; 问题提出&#xff0c;如何把Matlab(本文简称MT)的算法集成到Visual Studio(本文简称VS)里面运行&#xff1f; 本文&#xff0c;通过编制一个MT中最简单的加法函数&#xff0c;我们把他做成 MSVS C#能够使用的动态库&#xff0c;说明了MSVS C# 和 MT集成的最…

下拉框联动控制,明细数据重复检查

1、明细数据重复检查针对下拉框的字段&#xff0c;在重新赋空值时没成功&#xff0c;被注释了。 2、下拉联动控制如图 价格类型&#xff1a;优惠价&#xff0c;门店价 与员工关系&#xff1a;本人&#xff0c;父母&#xff0c;儿女&#xff0c;兄弟姐妹 优惠类型&#xff1a…

精华推荐 |【深入浅出Sentinel源码】「源码探索专题」完整剖析Alibaba微服务架构体系之分布式系统的流量防卫兵的基本介绍(入门源码介绍)

整剖析Alibaba微服务架构体系之分布式系统的流量防卫兵的基本介绍 推荐资料Sentinel 是什么&#xff1f;Sentinel 具有以下特征: Maven的pom中配置main函数介绍总结说明自定义的rule加载规则 Sentinel的限流原理滑动时间窗口算法固定时间窗口算法普通的滑动窗口做法Sentinel的滑…

ReactNative中样式与布局的书写

样式 const styles StyleSheet.create({container: {flex: 1,justifyContent: center,alignItems: center,backgroundColor: #F5FCFF,}, welcome: {fontSize: 20, textAlign: center,margin: 10, }, instructions: {textAlign: center,color: #333333,marginBottom: 5,}, …

七省数据局密集挂牌,期待规范引领数据行业蓬勃发展

今年开年以来&#xff0c;新一轮机构改革逐步在省级层面落地&#xff1a;多个省级数据局纷纷挂牌&#xff0c;全国各省市数据要素化市场加速推动。 1月10日&#xff0c;江苏省数据局率先正式挂牌&#xff0c;这是2023年国家数据局正式揭牌后&#xff0c;第一个成立的省级数据局…

AE/PR/达芬奇视频去闪烁插件---Flicker Free

Flicker Free是一款视频处理工具&#xff0c;主要用于去除视频中的闪烁和闪光问题&#xff0c;提高视频质量。它可以帮助用户快速、方便地处理视频&#xff0c;使其更加流畅、清晰。Flicker Free可以作为After Effects、Premiere Pro、Final Cut Pro、Avid、Resolve或Vegas的插…

C++ Linux动态库的编译和调用

一、C动态库编译 采用g编译C动态库&#xff0c;命令如下&#xff1a; g -fPIC -shared -o 动态库名 cpp文件名1.1 关于fPIC选项 首先了解动态库的载入时重定位。 一般linux的可执行文件都是elf格式&#xff08;一种二进制文件格式&#xff09;&#xff0c;在可执行文件的头部包…

在 PyTorch 中,怎么指定程序使用的 GPU。

在 PyTorch 中&#xff0c;你可以使用 CUDA_VISIBLE_DEVICES 环境变量来指定程序使用的 GPU。在你的命令行中运行脚本之前&#xff0c;你可以设置该环境变量。以下是如何指定显卡的一种方法&#xff1a; 假设使用第一张 GPU&#xff0c;可以运行以下命令&#xff1a; CUDA_VI…

【GaussDB数据库】序

参考链接1&#xff1a;国产数据库华为高斯数据库&#xff08;GaussDB&#xff09;功能与特点总结 参考链接2&#xff1a;GaussDB(DWS)介绍 GaussDB简介 官方网站&#xff1a;云数据库GaussDB GaussDB是华为自主创新研发的分布式关系型数据库。该产品支持分布式事务&#xff0c;…

Unity之射线检测

不知道大家有没有玩过红色警戒 —— 一款即时战略游戏&#xff0c;和罪恶都市一样小编小学的时候就开始玩了&#xff0c;这款游戏控制单位角色移动是通过鼠标的点击来实现。 同样的操作方法还有英雄联盟等很多游戏&#xff0c;那本篇文章小编就通过简单小实例来讲解这种操作在U…

2024最新Java高频面试题总结(附答案PDF)春招面试必备!

《Java面试全解析》1000道 面试题大全详解 本人是 2009 年参加编程工作的&#xff0c;一路上在技术公司摸爬滚打&#xff0c;前几年一直在上海&#xff0c;待过的公司有 360 和游久游戏&#xff0c;因为自己家庭的原因&#xff0c;放弃了阿里钉钉团队的 offer 回到了西安。 从…

openfire源码篇(一)检出源码并运行

openfire源码篇&#xff08;一&#xff09;检出源码并运行 源码检出 官方github地址 https://github.com/igniterealtime/Openfire 检出源码到本地&#xff08;请注意你的java版本&#xff0c;我检出的openfire 为 4.9.0-SNAPSHOT 此时jdk版本应为11&#xff09; 将源码检出…

API接口指南:打造高效开发流程的秘密武器

IP应用场景-IPv4&#xff0c;IPv4应用场景是获取IP场景属性的在线调用接口&#xff0c;具备识别IP真人度&#xff0c;提升风控和反欺诈等业务能力。IP应用场景基于地理和网络特征的IP场景划分技术&#xff0c;将IP划分为含数据中心、交换中心、家庭宽带、CDN、云网络等共计18类…

通过OpenIddict设计一个授权服务器02-创建asp.net项目

在这一部分中&#xff0c;我们将创建一个ASPNET核心项目&#xff0c;作为我们授权服务器的最低设置。我们将使用MVC来提供页面&#xff0c;并将身份验证添加到项目中&#xff0c;包括一个基本的登录表单。 创建一个空的asp.net core项目 正如前一篇文章中所说&#xff0c;授权…

苹果Find My可查找添加32件物品,伦茨科技ST17H6x芯片加速产品赋能

苹果最近更新的支持文档证实&#xff0c;从 iOS 16 开始&#xff0c;"Find My"可查找添加物品从16件增加到32件&#xff0c;AirTag 和“查找”网络中的物品利用“查找”网络的强大功能来发挥作用&#xff0c;这个网络由数亿台加密的匿名 Apple 设备构成。“查找”网络…

【MySQL】临时变量用法

力扣题 1、题目地址 2388. 将表中的空值更改为前一个值 2、模拟表 表&#xff1a;CoffeeShop Column NameTypeidintdrinkvarchar id 是该表的主键&#xff08;具有唯一值的列&#xff09;。该表中的每一行都显示了订单 id 和所点饮料的名称。一些饮料行为 null。 3、要求…

数据结构之栈的基本操作

该顺序栈涉及到了存储整型数据的顺序栈还有存储字符型数据的顺序栈 实现的功能有&#xff1a;入栈、出栈、判断是否为空栈、求栈的长度、清空栈、销毁栈、得到栈顶元素 此外根据上述功能&#xff0c;编写了数值转换&#xff08;十进制转化八进制&#xff09;方法、括号匹配方法…