C++类型转换+特殊类的设计+单例模式+IO流+空间配置器

news2024/10/7 12:25:34

索引

  • 类型转换
      • (1).C语言的类型转换
    • (2).C++四种类型转换
        • a.static_cast
        • b.reinterpret_cast
        • c.const_cast
        • d.dynamic_cast
          • volatile关键字(了解即可)
  • RTTL
  • 特殊类的设计
      • (1).设计一个类不能支持拷贝
      • (2).设计一个类,只能在堆上创建对象
      • (3).设计一个类,只能在栈上创建对象
      • (4).设计一个类,不能被继承
  • 单例模式
      • a.饿汉模式
      • b.懒汉模式
  • IO流
      • (1).C语言的输入与输出
      • (2).what is 流
      • (3).C++标准IO流
      • (4).C++文件IO流
      • (5).stringstream的简单了解
  • 空间配置器
      • (1).什么是空间配置器
      • (2).空间配置器实现大致原理

类型转换

(1).C语言的类型转换

两种类型转换

  • 隐式类型转换:编译器自动执行,相近类型才能成功

  • 显示的强制类型转换
    缺点

  • 隐式类型转换转换可能会出现精度的丢失

  • 显示类型转换将所有情况混合在一起,代码不够清晰

(2).C++四种类型转换

a.static_cast

用于相近之间的类型,与上述隐式类型转换差不多。

double a = 3.14;
	int b = static_cast<int>(a);

b.reinterpret_cast

不相近之间的类型转换,对应C语言之前的强制类型转换

double a = 3.14;
	int b = static_cast<int>(a);
	int* p = reinterpret_cast<int*>(b);

c.const_cast

去掉对象const属性,方便赋值

const int x = 2;
	int* ptr = const_cast<int*>(&x);
	*ptr = 3;

d.dynamic_cast

(前提是必须要有虚函数)

用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)
向上转换:子类对象指针/引用——>父类对象指针/引用(切片)
向下转换:用dynamic_cast更安全
dynamic_cast只能用于含父类虚函数的类
dynamic_cast会先检查受否转换成功,能成功则转换,不能则返回0

应用场景:
如果指针原本是指向子类的,然后由于切片传参,进入函数后再转换成子类是可以的,但是如果始终是指向父类的,如果不用dynamic_cast此时就是强制类型转换,会出些野指针的问题,用dynamic_cast会检查转换是否成功。

class A
{
public:
	virtual void f(){}
};
class B :public A
{
public:
	virtual void f() {

	}
};
void Fun(A* ptr)
{
	if (dynamic_cast<B*>(ptr))
		cout << "转换成功" << endl;
	else
	{
		cout << "转换失败" << endl;
	}
}

int main()
{
	
	A a;
	B b;
	A* pa = &a;
	B* pb = &b;
	Fun(pa);//转换失败
	Fun(pb);//转换成功

volatile关键字(了解即可)

是一个类型修饰符
在这里插入图片描述

RTTL

RTTL(Run-time Type identification)运行时类型识别

在这里插入图片描述

特殊类的设计

(1).设计一个类不能支持拷贝

拷贝只会发生在两个场景中:拷贝构造和赋值运算符重载

- 将拷贝构造和赋值运算符重载设计成私有并且只声明不定义
设置成私有是为了防止用户在类外定义,不定义是为了万一定义了,在类内部调用

- c++11直接在拷贝和赋值重载函数后面加delete,编译器删除该默认成员函数

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

class OnlyHeap
{
public:
	static OnlyHeap* CreatObject()
	{
		return new OnlyHeap;
	}
	static void DelObj(OnlyHeap* ptr)
	{
		delete ptr;
	}
private:
	//构造和拷贝构造都是设置为私有,此时无法调用
	OnlyHeap(){}
	OnlyHeap(const OnlyHeap& st);
	~OnlyHeap() {}
     /*析构函数私有的话,栈和静态的对象就不能
	 创建,因为此时其不能调用析构函数,同时
	 堆创建的对象也无法delete,此时写一个静态
	 析构函数如上即可*/
};
void test1()
{
	//OnlyHeap h1;//栈上
	//static OnlyHeap h2;//静态区
	//OnlyHeap* h3 = new OnlyHeap;//堆区
	上述都要调用构造函数,此时将构造函数设置为私有即可
	//OnlyHeap h4(h1);//拷贝构造在栈上生成对象、
	此时将拷贝构造也设置为私有即可
	OnlyHeap* h5 = OnlyHeap::CreatObject();//此时达到了只能在堆上创建对象
	//delete h5;//此时delete也会调用私有的析构函数,一样报错
	OnlyHeap::DelObj(h5);
}

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

class OnlyStack
{
public:
	static  OnlyStack CreatObject()
	{
		return OnlyStack();
	}
	//禁掉operator new
	/*如果类重载了operator new此时new这个对象时
	就会走重载的operator而不会走库中的operator new
	被禁掉了之后就无法再调用一个对象了。*/
private:
	//构造和拷贝构造都是设置为私有,此时无法调用
	OnlyStack():_a(0) {}
	OnlyStack(const OnlyHeap& st) = delete;
	//删除拷贝构造是因为防止出现以下这种情况
	//sattic OnlyStack copy(h1);//此时也是拷贝构造
private:
	int _a;
};
void test_Only_Stack()
{
	OnlyStack h1 = OnlyStack::CreatObject();//允许通过
	OnlyStack* h2 = new OnlyStack;//报错
	static OnlyStack h3;//报错
	sattic OnlyStack copy(h1)//报错
}

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

  1. 构造函数私有化,派生类不能调用基类构造函数,无法继承
  2. final关键字表示该类不能被继承
    eg
class A final
{};

单例模式

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

a.饿汉模式

无论程序后面是否使用,程序启动时就创建一个唯一的实例对象。

class SingLeton
{
public:
	static SingLeton* GetInstance()
	{
		return  m_instance;
	}
	void Print()
	{
		cout << "单例对象调用" << endl;
	}

private:
	//构造函数私有此时无法创建其他对象
	SingLeton(int a):_a(a)
	{
		//信息输入
	}
	//防拷贝
	SingLeton(const SingLeton& st) = delete;
	SingLeton& operator=(const SingLeton& st) = delete;

	static SingLeton* m_instance;//静态成员变量
	int _a;
};
SingLeton* SingLeton::m_instance = new SingLeton(2);
//静态成员变量定义在类域中不受访问限定符的限制
//所以即使构造函数是私有的,此时单例对象依旧可以初始化
void test_SingLeton()
{
	SingLeton::GetInstance();//这个类的单例对象
	SingLeton::GetInstance()->Print();
	/*SingLeton h1;
	SingLeton *h2 = new SingLeton;
	SingLeton copy(*SingLeton::GetInstance());
	此时构造函数和拷贝构造都是没用的,保证
	整个类中只有一个实例化对象*/
}

优点:不需要加锁,时间简单
缺点:可能会导致进程启动慢,且多个单例类对象实例启动顺序不一定。

eg:如果在main函数前就初始化单例对象,有可能构造函数需要进行的操作太多,这样的话,就可能会影响main函数的启动,所以一个大型程序启动慢的话,我们不清楚是构造函数太复杂(连接数据库什么的)还是整个程序卡死了。
eg:要求先初始化数据库对象,再初始化缓存对象,饿汉模式可能因为控制不住初始化的顺序而报错,都是在main函数之前初始化,顺序不确定。
懒汉模式可以控制——第一次调用时初始化

b.懒汉模式

一开始不创建对象,第一调用GetInstance再创建对象
涉及到加锁问题,实现后面补上

总结

  • 饿汉特点:简单一点,初始化顺序不确定,如果有依赖关系就会有问题,恶汉对象初始化慢且多个恶汉单例对象会影响程序启动
  • 懒汉特点:复杂一点,第一次调用时初始化,可以控制初始化顺序,延迟加载初始化,不影响程序启动推荐
  • 一般情况,单例模式不需要delete,因为整个程序中一直都要使用,程序结束了就会将空间还给操作系统。

IO流

(1).C语言的输入与输出

  • scanf:从标准输入设备(键盘)读取数据,并将值存放在变量中,printf():将指定的文字/字符串输入到标准输出设备(屏幕)C语言借助了相应的缓冲区来进行输入输出

在这里插入图片描述
理解缓冲区:

  • 可以屏蔽掉低级I/O的实现,低级I/O的实现依赖操作系统本身内核的实现,所以如果能够屏蔽这部分的差异,可以很容易写出可移植的程序
  • 可以实现"行"读取的行为,因为对计算机而言是没有"行"这个概念的,有了这部分就可以定义"行的概念"

(2).what is 流

即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且具有方向性的数据(其单位可以是bit,byte,packet)的抽象描述。
C++流是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从内存向外部输出设备(显示器)输出的过程。
特性:有序连续,具有方向性

  • 为了实现这种流动,c++定义了I/O标准库,这些每个类都被称为流/流类,以完成某方面的功能

(3).C++标准IO流

c++系统实现了一个庞大的类库,其中ios为基类,其他类都是直接或间接派生自ios类

在这里插入图片描述
c++标准库提供了四个全局对象cin,cout,cerr,clog
cin:标准输入即数据通过键盘输入到程序中
cout:标准输出即数据从内存流流向控制台(显示器)
cerr:用来标准错误的输出
clog:进行日志的输出
其中cout,cerr,clog是ostream类的三个不同对象,因此三个对象现在基本没区别,指示应用场景不同。

cout << "hello world" << endl;
	cerr << "hello world" << endl;
	clog << "hello world" << endl;
	//三者输出都是一样的结果

cin与cout可以直接输入和输出内置类型数据,标准库已经将所有内置类型的输入和输出全部重载了。
在这里插入图片描述
在这里插入图片描述

为什么在大数据输入的时候cin要比scanf慢?
因为cin是c++,它要同步C语言的输入流,如果输入的时候一下是cin,一下是scanf,两边的输入都不是直接到控制台,而是到缓存区,此时cin需要控制输入顺序什么的,而且scanf输入的时候类型%就确定了,而cin还需要推断。

(4).C++文件IO流

C++文件数据格式分为二进制文件文本文件
ifstream ifile(只输入用)
ofstream ofile(只输出用)
fstream iofile(既输入用又输出用)
在这里插入图片描述
在这里插入图片描述

struct ServerInfo
{
	char _address[32];
	//string _address;
	int _port;
	Date _date;
};
struct ConfigManager
{
public:
	ConfigManager(const char* filename)
		:_filename(filename)
	{}
	void WriteBin(const ServerInfo& info)
	{
		ofstream ofs(_filename, ios_base::out | ios_base::binary);
		//out:打开文件是为了写
		//binary:以二进制的方式打开
		//总体就是以二进制的方式将info写入_filename
		ofs.write((const char*)&info, sizeof(info));
	}
	void ReadBin(ServerInfo& info)
	{
		ifstream ifs(_filename, ios_base::in | ios_base::binary);
		//in:打开文件是为了读
		//binary:以二进制的方式打开
		//总体就是以二进制的方式将_filename中的内容读入info
		ifs.read((char*)&info, sizeof(info));
	}
	void WriteText(const ServerInfo& info)
	{
		ofstream ofs(_filename);//默认是文本的方式
		//将info中的内容以文本的方式写入到文件中
		ofs << info._address << " " << info._port << " " << info._date;
	}
	void ReadText(ServerInfo& info)
	{
		ifstream ifs(_filename);
		//将文件中的内容以文本的方式读入到info中
		ifs >> info._address >> info._port >> info._date;
	}
private:
	string _filename; // 配置文件
};

int main()
{
	ServerInfo winfo = { "192.0.0.1", 80, { 2021, 4, 10 } };
	// 二进制读写
	//二进制写
	ConfigManager cf_bin("test.bin");
	cf_bin.WriteBin(winfo);
	//二进制读
	ServerInfo rbinfo;
	cf_bin.ReadBin(rbinfo);
	cout << rbinfo._address << " " << rbinfo._port << " "
		<< rbinfo._date << endl;
	// 文本读写
	ConfigManager cf_text("test.text");
	//文本写
	cf_text.WriteText(winfo);
	ServerInfo rtinfo;
	//文本读
	cf_text.ReadText(rtinfo);
	cout << rtinfo._address << " " << rtinfo._port << " " <<
		rtinfo._date << endl;
	

	return 0;
}

在这里插入图片描述

(5).stringstream的简单了解

包含头文件sstream
该头文件下,标准库三个类:istringstream、ostringstream 和 stringstream,分别用来进行流的输入、输出和输入输出操作

C语言中将整型变量转换成一个字符串

  1. 使用itoa()函数
  2. 使用sprint()函数
    两个函数转换前需要给出保存结果的空间,但空间给多大,不好界定,并且如果转换格式不匹配,可能会得到错误信息
int n = 123456;
	char s1[32];
	_itoa(n, s1, 10);
	char s2[32];
	sprintf(s2, "%d", n);
	char s3[32];
	sprintf(s3, "%f", n);

  1. stringstream实际是在其底层维护了一个string类型的对象用来保存结果,因此多次数据类型转化时,一定要用clear()来清空才能正确转换,但clear不会将底层的string对象清空
  2. 因为底层就是string,所以stringstream常用来字符串的拼接,且使用s.str(“”)将底层对象设置为空字符串,此时用clear没用
    eg
stringstream  s;
	s << "a" << " " << "b";
	cout << s.str() << endl;//输出a b
	s.clear();
	s << "c";
	cout << s.str() << endl;//输出a bc
	s.str("");
	s << "d";
	cout << s.str() << endl;//输出d

  1. 使用s.str()返回stringstream底层的string对象
  2. stringstream使用string类对象代替字符数组,可以避免缓冲区溢出的危险,而且其会对参数类型进行推演,不需要格式化控制,也不会出现格式化失败的风险,因此使用更方便,更安全。
    在这里插入图片描述

空间配置器

(1).什么是空间配置器

空间配置器,顾名思义就是为各个容器高效的管理空间(空间的申请与回收)的默默工作。

在这里插入图片描述

(2).空间配置器实现大致原理

在这里插入图片描述
在这里插入图片描述
C++告一段落,开始Linux新篇章

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

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

相关文章

[C++数据结构](33)图,图的遍历,最小生成树,最短路径算法详解

文章目录图的基本概念图的存储结构邻接矩阵邻接表实现图的遍历广度优先遍历深度优先遍历最小生成树Kruskal 算法Prim 算法最短路径Dijkstra 算法Bellman-Ford 算法Bellman-Ford 算法的队列优化Floyd 算法图的基本概念 图(Graph)是由顶点集合及顶点间的关系组成的一种数据结构&…

uni-app入门:常用事件绑定与数据同步

1.常见事件与事件绑定 1.1点击事件bindtap 1.2 文本输入事件bindinput 1.3 切换事件bindtouchend 2.数据同步 2.1事件回调 2.2逻辑层中page对象中的中数据如何进行改变 2.3页面触发事件如何传参到page中数据 …

Android 基础知识1-开发环境搭建

1.1 Android开发准备工作 配置Android开发环境之前&#xff0c;首先需要了解Android对操作系统的要求。它可以使用Windows XP 已经以上版本、Mac OS 、Linux等操作系统&#xff0c;我是以Windows系统为例学习以及开发的。 1.2 开发包以及其工具的安装和配置 Android以Java作为…

内蒙古工程学院无线网络设计与规划

摘 要 I ABSTRACT II 第1章 绪论 1 1.1选题背景及意义 1 1.1.1选题背景 1 1.1.2选题意义 1 1.1.3国内外研究现状 2 1.2需求分析 3 1.2.1建设背景 3 1.2.2总体建设目标 4 1.2.4具体实施目标 5 1.3校园无线网在教育中的发展 6 第2章 无线网络的应用 7 2.1 无线网络的概述 7 2.1.1…

【毕业设计】60-基于ZigBee无线智能消防\烟雾报警逃生系统设计(原理图工程、源代码、低重复率参考文档、实物图)

【毕业设计】60-基于ZigBee无线智能消防\烟雾报警逃生系统设计&#xff08;原理图工程、源代码、低重复率参考文档、实物图&#xff09; 文章目录【毕业设计】60-基于ZigBee无线智能消防\烟雾报警逃生系统设计&#xff08;原理图工程、源代码、低重复率参考文档、实物图&#x…

Mybatis的一级缓存

目录前置生效场景一场景二失效场景一场景二场景三场景四场景五前置 什么是一级缓存: mybatis 默认开启一级缓存, SQLSession会话缓存, 每个SQLSession都会有各自的缓存 以下会演示一级缓存生效/失效的场景 项目地址: https://gitee.com/xmaxm/test-code/blob/master/chaim-cac…

初识golang微服务框架kratos

前言 今天给大家介绍一下Kratos&#xff0c;Kratos 一套轻量级 Go 微服务框架&#xff0c;包含大量微服务相关框架及工具,使用Kratos的原因主要是感觉原来使用的go-kit工具并不是很方便&#xff0c;期望用上kratos后开发会更快捷一些。 Kratos名字根据官方的説法是来源于:《战…

灵界的科学丨六、星际通信新科技──寻找外星人

摘自李嗣涔教授《灵界的科学》 外星先进文明科技领先地球的关键&#xff0c; 是外星人掌握了意识的物理&#xff0c; 能够制造仿照天眼的仪器&#xff0c; 自由进出虚数空间遨游宇宙&#xff0c;同时创造出瞬间科技。 人类未来学习的典范&#xff0c;就在天上无数的外星先进…

数据结构--线性表之顺序表

1.线性表定义 线性表&#xff08;List&#xff09;&#xff1a;零个或多个数据元素的有限序列。 线性表的数据集合为{a1,a2,…,an}&#xff0c;假设每个元素的类型均为DataType。其中&#xff0c;除第一个元素a1外&#xff0c;每一个元素有且只有一个直接前驱元素&#xff0c…

第三十三篇 transition-group 列表过渡

上一篇内容讲到的是transiotion&#xff0c;其中还记得有一个报错吗&#xff1f;如下&#xff1a; 先来回顾一下&#xff0c;<transition> 只能用于单个元素&#xff0c;如果在<transition>单中并列两个<p>标签&#xff0c;那么这样一来就会报以上这个错误&a…

六、表空间管理

六、表空间管理 1、查看表空间 使用DM Manager工具&#xff1a; 代码&#xff1a; -- 1、查看表空间名 select tablespace_name FROM SYS.DBA_TABLESPACES;-- 2、查看表空间名、表空间对应的数据文件地址、状态 select tablespace_name,file_name,status FROM dba_data_files;…

软件定义汽车产业生态创新白皮书

1 什么是软件定义汽车 1.1 驱动因素 汽车“新四化”的发展需要软件的加持 据大众汽车公开披露信息&#xff0c;未来平均每辆普通汽车软件代码量超 1 亿行。在电动化、智能化和网联化等的发展推动下&#xff0c;汽车将加速向高度数字化、信息化、智能化的移动终端发展。座舱娱…

CM311-1_YST_S905L3(B)_安卓9.0_设置无密码_默认打开adb_完美AI语音_线刷固件包

CM311-1_YST_S905L3(B)_安卓9.0_设置无密码_默认打开adb_完美AI语音_线刷固件包 固件特点&#xff1a; 1、修改dns&#xff0c;三网通用&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、无开机广告&#xff0c;无系统更新&#xff0c;不在被强制升…

LX12864P1屏幕使用介绍(ST7567驱动),显示横线、字符、图形

LX12864P1屏幕显示&#xff08;ST7567驱动&#xff09; 可编辑12864液晶模组&#xff0c;也就是液晶显示屏是有128*64个点阵组成。12864是一种图形点阵液晶显示器&#xff0c;它主要采用动态驱动原理由行驱动—控制器和列驱动器两部分组成了128(列)64(行)的全点阵液晶显示此显…

全国地级市城镇化和协调发展指数测算数据(2005-2019)六份数据

全国地级市城镇化和协调发展指数测算数据&#xff08;2005-2019&#xff09;六份数据 1、范围&#xff1a;受数据限制&#xff0c;剔除了新疆和西藏的城市共包括287个地级市 2、时间区间为&#xff1a;2005-2019年 3、六分数据包括&#xff1a; 地级市城镇化发展水平&#…

多线程入门

多线程简介 1. 进程/线程 # 进程 - 进程由指令和数据组成&#xff0c;指令要运行&#xff0c;数据要读写&#xff0c;必须将指令加载到CPU&#xff0c;数据加载到内存。指令运行过程中还需要用到磁盘&#xff0c;网络等IO设备 - 进程用来加载指令&#xff0c;管理内存&#x…

CentOS7 安装rabbitMQ步骤

全程使用root权限 1、修改主机名称 hostnamectl set-hostname rmq158 2、输入命令&#xff1a;vi /etc/hosts修改hosts文件 3、重启 4、WINSCP传输两个包到/usr/local下面 5、tar -xvf otp_src_21.3.tar.gz cd otp_src_21.3 ./configure --prefix/usr/local/erlang 6、yum i…

教学:制作 GitHub 同步近期博客卡片

这几天看到有小伙伴将自己近期更新的博客同步显示到了 GitHub 主页&#xff0c;这么有趣的小卡片我是一定要尝试一把的&#xff0c;完整的教程我已经整理好了&#xff0c;一起搞起来吧~ 2. 开始教程 2.1 实现流程&#xff1a; Github 的主页装修主要讲的就是主页的 Markdown 文…

Spring Security自定义验证码登录

本文内容来自王松老师的《深入浅出Spring Security》&#xff0c;自己在学习的时候为了加深理解顺手抄录的&#xff0c;有时候还会写一些自己的想法。 验证码登录也是项目中一个常见的需求&#xff0c;但是Spring Security并未提供自动化配置方案。所以需要开发者自行定义。这里…

Spring的创建和使用

1. 创建Spring项目 1.1 创建一个 Maven 项目 不需要使用任何模板, 点击下一步.注:所有的名称都不能包含中文.Maven仓库中的结构: 1.2 添加 Spring 框架支持 在Spring 的 配置文件 中添加依赖 spring-context: Spring的上下文spring-beans: 管理Spring对象(bean) <depende…