C++语法(26)--- 特殊类设计

这篇具有很好参考价值的文章主要介绍了C++语法(26)--- 特殊类设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++语法(25)--- 异常与智能指针_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/131537799?spm=1001.2014.3001.5501

 目录

1.特殊类设计

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

C++98

C++11

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

1.封掉所有拷贝

C++98

C++11

2.封掉析构函数

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

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

1.C++98

2.C++11 final

2.单例模式

1.设计模式

2.单例模式

1.饿汉模式

2.懒汉模式

3.单例对象释放问题


1.特殊类设计

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

C++98

将拷贝函数只声明不实现,并且放到私有处。(只不过,在类型内部调用另外的函数进行拷贝就没有办法防止了)

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

C++11

在函数申明后面加入 =delete

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

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

1.封掉所有拷贝

C++98

1.先将构造函数封死,这样就无法在栈上创造对象了。但是我们需要提供一个函数调用,使得其在堆上创造对象。

2.创造堆上的函数不能直接修饰,这样会出现逻辑谬论(即想要创造对象,需要调用函数;想要调用函数,需要先创造对象)。所以这里的解决方式是设置静态函数,不需要this指针,所以不需要生成所谓对象才能调用,可以直接调用。

3.特别注意,其实拷贝构造函数也需要被处理一下,因为如果在外部先构造堆上的,随后通过解指针调用给拷贝构造,那么其实也是不算合格的。

class HeapOnly
{
public:
    static HeapOnly* CreateObject()
    {
        return new HeapOnly;
    }
private:
    HeapOnly() {}
    HeapOnly(const HeapOnly&) {}
}

int main()
{
    HeapOnly* php = HeapOnly::CreateObject();
}
C++11
class HeapOnly
{
public:
    static HeapOnly* CreateObject()
    {
        return new HeapOnly;
    }
    HeapOnly(const HeapOnly&) = delete;
    HeapOnly(const HeapOnly&)  = delete;
};

2.封掉析构函数

1.将析构函数封掉也能达到相同的效果,因为构造了就需要被析构,类型没有检查到可以析构就会报错。

2.此时堆上的类需要被释放掉,也需要重新构造一个destory函数,其类型是类型的指针,不可以是对象本身,因为这样就是手动调用析构函数了。只要调用destory就能释放堆上的空间。

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

这样设计使得不能创建在堆和静态上。

class StackOnly
{
public:
    static StackOnly CreateObj()
    {
        return StackOnly();
    }
private:
    StackOnly()
    :_a(0)
    {}
private:
    int _a;
};

这样的设计使得不能在堆上创建但是,能产生静态的对象。

// 禁掉operator new可以把下面用new 调用拷贝构造申请对象给禁掉
void* operator new(size_t size) = delete;
void operator delete(void* p) = delete;

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

1.C++98

构造函数私有化,子类本来要调用父类的构造函数,没有则不能被继承。

class NonInherit
{
public:
    static NonInherit GetInstance()
    {
    return NonInherit();
    }
private:
    NonInherit()
    {}
};

2.C++11 final

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

2.单例模式

1.设计模式

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

一些设计理念:迭代器模式,配接器模式,单例模式,工厂模式,观察者模式

2.单例模式

一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
使用样例:内存池的申请

1.饿汉模式

特点:

一开始(在main函数之前)就创造对象,就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象

缺点:

1.由于初始化在main函数之前,这样的类数据过多,会使得启动慢;

2.多个单例类有初始化依赖关系,饿汉模式无法控制类的初始化先后关系

class InfoSingleton
{
public:
	static InfoSingleton& GetInstance()
	{
		return _sins;
	}

	void Insert(string name, int money)
	{
		_info[name] = money;
	}

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

private:
	InfoSingleton()
	{}

	InfoSingleton(const InfoSingleton& info) = delete;

	InfoSingleton& operator=(const InfoSingleton& info) = delete;

	map<string, int> _info;

private:
	static InfoSingleton _sins;
};

InfoSingleton InfoSingleton::_sins;

int main()
{
	InfoSingleton::GetInstance().Insert("张三", 1000);
	InfoSingleton& info = InfoSingleton::GetInstance();
	info.Insert("李四", 100);
	//InfoSingleton copy = InfoSingleton::GetInstance(); //拷贝构造
	//copy.Insert("***", 10000);
	return 0;
}

2.懒汉模式

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

2.如果类之间存在依赖关系,也可以使用懒汉模式(延迟加载)。

template<class Lock>
class LockGuard
{
public:
	LockGuard(Lock& lk)
		:_lk(lk)
	{
		_lk.lock();
	}

	~LockGuard()
	{
		_lk.unlock();
	}

private:
	Lock& _lk;
};

class _InfoSingleton
{
public:
	//线程安全问题,多线程一起调用创建对象
	static _InfoSingleton& GetInstance()
	{
		//双检查增加效率
		if (_psins == nullptr) {
			LockGuard<mutex> lock(*_smtx);
			if (_psins == nullptr)
			{
				_psins = new _InfoSingleton;
			}
		}
		return *_psins;
	}

	void Insert(string name, int money)
	{
		_info[name] = money;
	}

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

private:
	_InfoSingleton()
	{}

	_InfoSingleton(const _InfoSingleton& info) = delete;

	_InfoSingleton& operator=(const _InfoSingleton& info) = delete;

	map<string, int> _info;

private:
	static _InfoSingleton* _psins;
	static mutex* _smtx;
};

static _InfoSingleton* _psins = nullptr;
static mutex* _smtx;

1.这样写是懒汉模式,只创建一次,并且在main函数调用之后创建。

2.该代码有线程安全问题,在C++11后得到解决。

static _InfoSingleton& GetInstance()
{
	static _InfoSingleton sinst;
	return sinst;
}

注意:

1.懒汉模式需要注意线程安全问题,所以我们在类中需要有一个唯一的锁,确保判断时是串行访问的。

2.每次都先加锁再进行判断是否为空,其实是非常低效,所以我们需要双判断,第一次判断是为了抛去已经创建过的节省加锁的时间,第二次判断是为了创建对象使用的,而锁夹在中间确保第二次的判断是串行的。

3.饿汉模式不需要注意线程安全问题,因为饿汉在main调用之前就已经存在了,没有所谓的线程可以创建其他的对象。

3.单例对象释放问题

1.一般而言单例类不需要释放内存,因为单例出现的环境就是全局的,它的目的就是陪到进程执行到最后,那么其实不释放,进程结束后,操作系统也会将这一部分的资源回收。

2.特别的,如果我们需要在最后单例有一定要求,我们可以手写出析构,比如进程结束需要保存一些数据到文件中,那么我们析构可以手写要求。文章来源地址https://www.toymoban.com/news/detail-609046.html

到了这里,关于C++语法(26)--- 特殊类设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从C语言到C++_37(特殊类设计和C++类型转换)单例模式

    目录 1. 特殊类设计 1.1 不能被拷贝的类 1.2 只能在堆上创建的类 1.3 只能在栈上创建的类 1.4 不能被继承的类 1.5 只能创建一个对象的类(单例模式)(重点) 1.5.1 饿汉模式 1.5.2 懒汉模式 2. 类型转换 2.1 static_cast 2.2 reinterpret_cast 2.3 const_cast 2.4 dynamic_cast 3. RTTI(了解)和类型转换常见面

    2024年02月10日
    浏览(50)
  • Rust 程序设计语言学习——基础语法

    Rust 语言是一种高效、可靠的通用高级语言。其高效不仅限于开发效率,它的执行效率也是令人称赞的,是一种少有的兼顾开发效率和执行效率的语言。 Rust 语言由 Mozilla 开发,最早发布于 2014 年 9 月。Rust 的编译器是在 MIT License 和 Apache License 2.0 双重协议声明下的免费开源软

    2024年01月22日
    浏览(52)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 三)

    在开始之前,先明确自定义组件和页面的关系: 自定义组件: @Component 装饰的 UI 单元,可以组合多个系统组件实现 UI 的复用。 页面:即应用的 UI 页面。可以由一个或者多个自定义组件组成, @Entry 装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有

    2024年02月16日
    浏览(63)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 五)

    如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器@Styles。 @Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位

    2024年02月17日
    浏览(56)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 一)

    ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在 TypeScript (简称 TS )生态基础上做了进一步扩展,继承了 TS 的所有特性,是 TS 的超集。因此,在学习 ArkTS 语言之前,建议开发者具备 TS 语言开发能力。 当前, ArkTS 在 TS 的基础上主要扩展了如下能力: 基本语法:

    2024年02月16日
    浏览(70)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 二)

    在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成

    2024年02月04日
    浏览(54)
  • HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 四)

    当创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量

    2024年02月17日
    浏览(53)
  • 【C++】特殊类设计

    欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 🏠个人专栏:题目解析 🌎推荐文章:【LeetCode】winter vacation training 拷贝只会放生在两个场景中: 拷贝构造函数 以及 赋值运算符重载 ,因此想要让一个类禁止拷贝, 只需让该类不能调用拷贝构造函数以及赋值运算符重载即

    2024年01月17日
    浏览(41)
  • C++ 特殊类设计

    如果只能在堆上创建对象,就是限制在栈上和静态区中创建对象,步骤如下: 方法一:将构造函数私有化. 将构造函数设置为私有,以防用户在栈上或者静态区直接调用构造函数创建对象. 在公有区域提供一个静态的成员函数,在该静态成员函数中使用new创建对象,此时因为new在成员函

    2024年02月11日
    浏览(35)
  • C++进阶(十六)特殊类设计

    📘北尘_ :个人主页 🌎个人专栏 :《Linux操作系统》《经典算法试题 》《C++》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 拷贝只会放生在两个场景中: 拷贝构造函数以及赋值运算符重载 ,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运

    2024年02月19日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包