C++进阶—特殊类设计

ADP在线自适应动态规划之持续激励条件 在线自适应动态规划之持续激励条件 在在线自适应动态规划算法中,需要通过满足持续激励条件(Persistent Excitation Condition)保证critic网络权值的收敛性,一般的做法都是在算法初期在输入端引入探测噪声(Probing Noises)来保证数据的丰富性,但是由于在输入端引入噪声会给系统带来一些不好的影响,甚至可能破坏系统的稳定性。因此,出现了一些其他的方法来避免引入探测噪声,受阅读所限,我目前了解两种: Concurrent Learning(CL) Experience Re 阅读详情

第一章:设计一个类,不能被拷贝

拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。

C++98

将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可。

class CopyBan {
	// ...

private:
	CopyBan(const CopyBan&);
	CopyBan& operator=(const CopyBan&);
	//...
};

原因:

  1. 设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,就可以不能禁止拷贝了
  2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不会防止成员函数内部拷贝了。

C++11

C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上=delete,表示让编译器删除掉该默认成员函数。

class CopyBan {
	// ...
	CopyBan(const CopyBan&) = delete;
	CopyBan& operator=(const CopyBan&) = delete;
	//...
};

第二章:设计一个类,只能在堆上创建对象

方案一:析构函数私有化

class HeapOnly {
public:
	////设置为静态函数的原因:它需要能够在不依赖对象实例的情况下调用,同时还要能访问私有析构函数。
	////因为都是在堆上创建的对象,只有对象的指针,而成员函数要通过对象才能调用。所以只能设置为静态函数
    ////不能在Destory里调用析构函数,因为析构是成员函数需要this才能调用,而Destory是静态成员函数没有this指针
	//static void Destory(HeapOnly* ptr) { delete ptr; }

	void Destory() { delete this; }
private:
	~HeapOnly() { cout << "~HeapOnly()" << endl; }
};
int main() {
	//在栈上创建对象时,编译器需要在对象离开作用域时自动调用析构函数来销毁对象。
	//如果析构函数是私有的,编译器无法在main函数或其他外部函数中直接调用析构函数,因此会报错。
	//hp离开作用域时,编译器尝试调用 ~HeapOnly(),但它是私有的,无法访问。
	//HeapOnly hp;//报错
	
	//堆上创建对象不会立即涉及析构函数的调用,因此可以成功。
	HeapOnly* ptr = new HeapOnly;
	//HeapOnly::Destory(ptr);//static void Destory(HeapOnly* ptr)
	ptr->Destory();
	return 0;
}

方案二:构造函数私有化

class HeapOnly {
public:
	////CreateObj() 是一个普通成员函数,必须通过一个 HeapOnly 对象调用。
	////但构造函数是私有的,你无法先创建一个 HeapOnly 对象去调用 CreateObj(),导致死锁
	//HeapOnly* CreateObj() { return new HeapOnly; }

	//static 成员函数不依赖对象实例,可以直接用 HeapOnly::CreateObj() 调用。
	static HeapOnly* CreateObj() { return new HeapOnly; }

	HeapOnly(const HeapOnly& hp) = delete;
private:
	HeapOnly() { cout << "HeapOnly()" << endl; }
};
int main() {
	//HeapOnly* ptr = new HeapOnly;//报错
	HeapOnly* ptr = HeapOnly::CreateObj();
	
	////该类还不完善,可以用拷贝构造在栈上创建对象,还需禁止拷贝构造
	//HeapOnly copy(*ptr);
	return 0;
}

第三章:设计一个类,只能在栈上创建对象

析构函数私有化无效。
栈对象的析构由编译器自动调用,如果析构函数私有化,编译器无法在作用域结束时调用析构函数,导致编译错误。栈对象必须公有析构函数,否则无法自动销毁。
 

将构造函数私有化,然后设计静态方法创建对象返回即可。

class StackOnly {
public:
	static StackOnly CreateObj() { 
		StackOnly obj;
		return obj;
	}
	
	////如果禁止拷贝构造上面无法返回对象
	//StackOnly(const StackOnly&) = delete;

	////new会调用operator new,而它是全局的,所以重载一个专属的。
	////当new这个类的对象时,就是调用该operator new,而不是全局的
	////演示实现类专属的operator new
	//void* operator new(size_t size) {
	//	cout << "void* operator new(size_t size)" << endl;
	//	return malloc(size);
	//}
	
	//禁用operator new相当于间接禁用new
	void* operator new(size_t size) = delete;

private:
	StackOnly() { cout << "HeapOnly()" << endl; }
};

int main() {
	//StackOnly ptr = new StackOnly;//报错
	StackOnly obj = StackOnly::CreateObj();

	//该类仍有缺陷。编译器会自动生成一个公有的拷贝构造函数,因此可以用已有对象 obj 来构造堆对象。
	StackOnly* ptr = new StackOnly(obj);
	return 0;
}

第四章:请设计一个类,不能被继承

C++98方式

// C++98中构造函数私有化,派生类中调不到基类的构造函数。则无法继承
class NonInherit {
public:
	static NonInherit GetInstance() {
		return NonInherit();
	}
private:
	NonInherit() {}
};

C++11方法

final关键字,final修饰类,表示该类不能被继承。

class A  final {
	// ....
};

第五章:请设计一个类,只能创建一个对象(单例模式)

设计模式:
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。为什么会产生设计模式这样的东西呢?就像人类历史发展会产生兵法。最开始部落之间打仗时都是人拼人的对砍。后来春秋战国时期,七国之间经常打仗,就发现打仗也是有套路的,后来孙子就总结出了《孙子兵法》。孙子兵法也是类似。

使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。

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

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

饿汉模式

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

//优点:实现简单
//缺点:1.可能会导致进程启动慢
//2.如果有两个单例启动先后顺序,那么饿汉无法控制
//假设有两个单例A B,要求A单例先启动,B再启动(因为B需要调用A)
//静态对象可以理解为全局对象,先初始化谁无法控制
class A {
public:
	////如果 GetInstance() 不是静态的,就必须先有一个 A 的对象才能调用它,但构造函数是私有的,无法创建对象 → 死锁。
	////因此,必须通过 static 方法直接访问 _inst,而不依赖任何实例。
	//A* GetInstance() { return &_inst; }

	static A* GetInstance() { return &_inst; }

	void Add(const string& key, const string& value) {
		_dict[key] = value;
	}

	void Print() {
		for (auto& kv : _dict)
			cout << kv.first << ":" << kv.second << endl;
		cout << endl;
	}
private:
	A() {};
	A(const A& aa) = delete;
	A& operator=(const A& aa) = delete;//禁用拷贝构造最好也禁用赋值
	map<string, string> _dict;
	int _n = 0;

	//静态成员变量属于类本身,而不是类的某个特定对象(因此,A::_inst是一个全局唯一的A类对象)
	//静态成员的定义是在类的作用域内完成的,所以可以访问私有构造函数
	static A _inst;
};
A A::_inst;

int main() {
	A::GetInstance()->Add("sort", "排序");
	A::GetInstance()->Add("left", "左边");
	A::GetInstance()->Add("right", "右边");
	A::GetInstance()->Print();

	////该类仍有缺陷,还要禁用拷贝构造
	//A copy(*A::GetInstance());
	//copy.Print();

	//A::GetInstance()->Add("left", "剩余");
	//A::GetInstance()->Print();//这个改了
	//copy.Print();//这个没改

	//*A::GetInstance() = *A::GetInstance();//禁用赋值,避免自己给自己赋值

	return 0;
}

如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好。

懒汉模式

如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。

//优点:第一次使用实例对象时,创建对象。进程启动无负载。多个单例实例启动顺序自由控制。
//懒汉模式的线程安全问题:在多线程环境下,如果多个线程同时首次调用 GetInstance(),
//可能会导致单例对象被构造多次,从而破坏单例的唯一性。
//new的懒汉对象一般不需要释放,进程正常结束会释放资源
class B {
public:
	//第一次调用该函数,_inst为空,创建B对象。
	//第二次调用该函数,_inst不为空,直接返回_inst
	static B* GetInstance() { 
		if (_inst == nullptr)
			_inst = new B;
		return _inst;
	}

	void Add(const string& key, const string& value) {
		_dict[key] = value;
	}

	void Print() {
		for (auto& kv : _dict)
			cout << kv.first << ":" << kv.second << endl;
		cout << endl;
	}

	//DelInstance()确实提供了双重功能:
	//a) 作为gc类的自动释放接口
	//b) 作为用户手动释放的接口
	static void DelInstance() {
		if (_inst) {
			delete _inst;//这里会调用析构
			_inst = nullptr;
		}
	}
private:
	B() {};
	~B() {
		//持久化:要求把数据写到文件
		cout << "数据写到文件" << endl;
	}
	B(const B& aa) = delete;
	B& operator=(const B& aa) = delete;//禁用拷贝构造最好也禁用赋值
	map<string, string> _dict;
	int _n = 0;

	//静态成员变量属于类本身,而不是类的某个特定对象(因此,A::_inst是一个全局唯一的A类对象)
	//静态成员的定义是在类的作用域内完成的,所以可以访问私有构造函数
	static B* _inst;

	//内部类是外部类的友元
	//gc类在这里相当于在懒汉模式中嵌入了一个"饿汉式"的辅助对象。
	//gc类的实例_gc是静态成员,会在程序启动时初始化(饿汉式)。
	//gc的析构函数会调用DelInstance()来释放单例对象。
	class gc {
	public:
		~gc() { DelInstance(); }
	};
	static gc _gc;
};
B* B::_inst = nullptr;
B::gc B::_gc;
//B::gc:表示这是 B 类内部的嵌套类 gc 类型。
//B::_gc:表示这是 B 类的静态成员变量 _gc。

int main() {
	B::GetInstance()->Add("sort", "排序");
	B::GetInstance()->Add("left", "左边");
	B::GetInstance()->Add("right", "右边");
	B::GetInstance()->Print();

	return 0;
}

Python爬虫实战:用最新技术高效下载摄影网站图片 本文将深入探讨如何利用Python最新技术栈构建一个功能完整的摄影网站图片爬虫。我们将使用异步编程、智能反爬策略和现代化工具,实现高效、可靠的图片下载系统。高性能异步架构:使用asyncio实现高并发下载智能反爬策略:支持多种反爬措施和浏览器模拟多网站适配:可解析多种摄影网站结构数据管理:完整的下载记录和统计功能扩展性强:支持代理、分布式等高级功能用户友好:提供进度显示和详细日志。 阅读详情

相关推荐

PP触发EWM产生PMR捡配

PP触发EWM产生PMR捡配 前言 PMR: Production Material Request 在流程订单/生产订单下达后,可以在EWM中产生PMR,在EWM中, PMR其实代表了ERP中的流程订单/生产订单。 You can use SAP EWM in conjunction with the following PP application components: • Production Orders • Process Orders • Repetitive Manufacturing •

ZevYang的博客 1918

[cpp进阶]C++特殊类设计

为什么会产生设计模式这样的东西呢?就像人类历史发展会产生兵法。最开始部落之间打仗时都是人拼人的对砍。后来春秋战国时期,七国之间经常打仗,就发现打仗也是有套路的,后来孙子就总结出了《孙子兵法》。孙子兵法也是类似。

weixin_53027918的博客 961

博途S7-1200与昆仑通态MCGS纯仿真联调实战指南

本文详细介绍了博途S7-1200与昆仑通态MCGS纯仿真联调的实战指南,包括环境搭建、配置步骤、通信桥接及故障排除。通过TIA Portal和MCGS Pro搭建的仿真环境,可实现80%以上的基础功能验证,适用于工业自动化学习和开发,大幅降低硬件投入成本。

weixin_26834815的博客 439

C++进阶 特殊类的设计

介绍C++中几种特殊类的设计以及单例模式

小萌新的博客 1094

SigmaStar(星宸科技)SSC33X系列

目前,SSC33X系列已经量产了接近两年,SDK成熟稳定,功耗表现良好,图像效果出色,广泛应用在AI枪机、AI球机、AI云台机、多目摄像机、停车场闸机、人脸门禁、人脸锁、门铃猫眼等产品上。

Comake Online的博客 1万+

微型纵向加密在新能源场站中的实战部署与运维避坑指南

本文详细解析了微型纵向加密在新能源场站中的实战部署与运维技巧。通过国密算法SM4实现数据加密,确保新能源场站通信安全,同时提供非侵入式部署方案和运维避坑指南,帮助提升网络稳定性和运维效率。

weixin_30505225的博客 596

c++进阶之——特殊类设计

了,就可以。

2201_75453663的博客 1026

这才是 Python 的正确玩法!用强化学习 (RL) 训练 AI 玩《王者荣耀》,胜率 90%!

大家打排位时,一定遇到过那种“意识神级、操作零失误”的对手,或者“走位呆滞、送人头”的队友。以前的“人机”是程序员写死的脚本(If 血量<20% Then 回城)。而现在的顶级 AI(如腾讯绝悟、OpenAI Five),是靠强化学习 (Reinforcement Learning)自己“左右互搏”练出来的。今天,我们不谈枯燥的数学公式,我将手把手教你用,搭建一个能玩 MOBA 游戏的 AI Agent。即使不能去 KPL 打职业,虐一下钻石局还是绰绰有余的!

BUG猿的博客 1182

【C++进阶】特殊类设计

C++特殊类设计详解

m0_60338933的博客 1263

Cesium中级开发教程之二十二:视锥体

教程示例网站:https://thomaz529.github.io。

883

vscode中运行gcc -v命令失败了,提示:gcc不是内部或外部命令...如何解决?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!

**My Coding Family** 975

C++进阶-特殊类设计

拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,。C++98将,delete除了释放new申请的资源外,如果在默认成员函数后跟上=delete,。

weixin_64423718的博客 678

8、音频运行时系统的架构设计

本文深入探讨了音频运行时系统的分层设计及其优势,包括逻辑层和物理层的功能划分。通过分层设计,开发者可以更轻松地管理和优化音频资源,确保其在不同平台上的高效运行。文章还介绍了平台适配与优化、错误处理与调试以及未来发展方向等内容,为开发者提供了宝贵的参考和指导。

juice的博客 461

C++进阶--特殊类设计

在C++类与对象中,C++98中,一个空类中编译器会默认生成六个成员函数,分别是构造函数、析构函数、拷贝构造函数、赋值运算符重载函数、普通对象和const对象取地址重载函数;在C++11中增加了移动构造和移动赋值。而对于一些特殊的类,当用户未显示生成相应的方法时,我们也不希望编译器生成该方法。所以每当设计一个类的时候都得根据用户的需求来进行相应的设计。

sushang的博客 1113

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【C++进阶】特殊类的设计——单例模式详解

特殊类的设计我们只要知道常用的就可以了,单例模式还是比较的常用,所以要好好理解一下。下一节我们会带来C++的收尾内容,到这里我们C++的主要内容也快结束了,但是继续深挖C++的话还是有很多东西要学,所以希望大家可以持续学习,我也会带来更多的内容去分享。

weixin_64906519的博客 1056

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

C++进阶 — 特殊类设计

使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。比如迭代器模式,配接器(适配器)模式,单例模式,工厂模式,观察者模式等。这些都是设计模式。

一个努力拼搏的人 900

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

C++进阶篇,特殊类设计

C++的一些特殊类,重点介绍了单例模式。

CHAKMING1的博客 1160

C++进阶(十六)特殊类设计

分享c++特殊类设计的知识。

2301_78995005的博客 1443

【C++进阶学习】第十四弹——特殊类设计——探寻各种情况下类的应用

【C++进阶学习】第十四弹——特殊类的设计:探索特殊条件下类的设计方式,加深对类的理解和应用

2301_80220607的博客 3974

【C++进阶】特殊类设计 && 单例模式

上述写法C++11之前不能用,局部静态单例对象构造初始化无法保证线程安全问题,C++11后可以用,C++11之后进行了优化,就不会出现线程安全的问题了!初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。C++98中构造函数私有化,派生类中调不到基类的构造函数。final关键字,final修饰类,表示该类不能被继承。但是上述代码又会带来新的问题,假如是在多线程情况下跑呢?C++11就直接删除该默认成员函数!

2301_78611726的博客 605

C++进阶(9)特殊类设计

特殊类的设计

2301_79907403的博客 739

[c++进阶(三)]单例模式及特殊类的设计

特殊类的设计和单例模式就讲到这了,只单说概念其实大家对于单例模式的强大性还是理解的不够深刻,只有在结合项目一起使用时,那么理解就会快速增加了。拓展:单例模式只是设计模式中的一种,还有工厂模式,适配器模式等等,有想了解这些设计模式的可以自行查阅资料。设计模式 - 概览 | C++ 全栈知识体系 (stibel.icu)

weixin_62196764的博客 1159

(C++进阶)设计特殊类

目录1 只能在堆上创建对象的类1.1 实现方式1.2 实现2 只能在栈上创建对象的类2.1 实现方法2.2 实现2.3 屏蔽new方法实现3 不能被拷贝的类3.1 C++983.1.1实现3.2 c++113.2.1 实现4 不能被继承的类4.1 c++984.2 c++115 只能创建一个对象的类(单例模式)5.1 设计模式5.2 单例模式5.2.1 饿汉模式5.2.2 懒汉模式5.2.3 懒汉模式与饿汉模式的对比 2 只能在栈上创建对象的类 2.1 实现方法 将构造函数私有化,然后设计静态方法创

qq_57594025的博客 204

【C++进阶之路】特殊类的设计

C++特殊类的设计。只能在堆上创建的对象,只能在栈上创建的对象,不能被拷贝的对象,不能被继承的对象,只能被单个使用的类。

Shun_Hua的博客 278

C++进阶(13)特殊类设计

如果一个类不能被继承的化,可以用final关键字进行修饰这个类;也可以将该类的构造函数进行私有化,在派生类构造中,钓不到基类的构造,间接的禁止该类被继承。如果想要用户只能在堆上创建类的话,那就不能让用户直接访问到构造函数和赋值拷贝,因为这种默认的方式都是在栈上创建类对象的。类的拷贝只会在两个场景中出现:一个是构造的时候—拷贝构造,另一个则是赋值的时候。因为只能在栈上创建,所以只需要将new和delete。不管将来用不用,程序启动时就创建一个唯一的实例对象。延迟加载,当需要用到时,才创建对象。

敲代码嘞~的博客 503

【1++的C++进阶】之特殊类设计

让对象只能在堆上创建,那么我们应该将构造函数,拷贝构造都私有化,使得用户不能自己在栈上创建对象。我们再提供一个静态函数的接口,其返回的是一个指向堆上对象的指针。与上述一样,我们将构造函数私有化,使得对象不能够直接在类外创建在栈上的对象。我们将其构造,拷贝与赋值私有化,防止其在类外创建对象,并且在类中声明了一个自己的静态对象,再提供一个访问它的全局访问点。该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。单例模式的实现有两种:饿汉模式和懒汉模式。

m0_63135219的博客 2108
上一篇: C++进阶—智能指针
下一篇: C++进阶—C++的类型转换
Awkwardx
博客等级 码龄5年 341粉丝 82原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值