【C++学习笔记】特殊类设计

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

1 设计一个不能被拷贝的类

C++类中只有两个拷贝的方式:拷贝构造函数和赋值运算符重载。想要设计一个不能被拷贝的类,只要想办法让类中这两种拷贝的方式不能使用即可。

1.1 C++98的方法

因为在C++的类中,这两种拷贝的方式是默认存在的,所以需要在类中只声明不定义即可。
但是由于在用户在类外还能定义,所以必须将拷贝构造函数和赋值运算符重载设置成private

#include <iostream>

using namespace std;
class copy_ban
{
public:
	copy_ban(int x = 0)//有参构造
		:_x(x)
	{}
private:
	int _x;
	copy_ban(const copy_ban& co);
	copy_ban& operator=(const copy_ban& x);
};
int main()
{
	copy_ban c1(1);
	copy_ban c2(c1);//error,不能使用拷贝构造
	copy_ban c3;
	c3 = c1;//error,不能使用赋值运算符重载
	return 0;
}

1.2 C++11方法

C++11扩展了delete的用法,在默认成员函数后面加上“=delete”就不允许使用该成员函数了。

#include <iostream>

using namespace std;
class copy_ban
{
public:
	copy_ban(int x = 0)//有参构造
		:_x(x)
	{}
	copy_ban(const copy_ban& co) = delete;
	copy_ban& operator=(const copy_ban& x) = delete;
private:
	int _x;
};
int main()
{
	copy_ban c1(1);
	copy_ban c2(c1);//error,不能使用拷贝构造
	copy_ban c3;
	c3 = c1;//error,不能使用赋值运算符重载
	return 0;
}

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

实现方式:

  1. 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。
  2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建
#include <iostream>

using namespace std;

class heap_only
{
public:
	heap_only(const heap_only& h) = delete;
	static heap_only* create(int x)
	{
		heap_only* p = new heap_only(x);//new 出来的空间在堆上
		return p;
	}
private:
	int _x;
	heap_only(int x = 0) : _x(x){}
};

int main()
{
	//heap_only h1(1);//error,构造函数被设置成私有,类外不能使用
	heap_only* h2 = heap_only::create(2);//correct,在堆上创建了空间
	//heap_only h3(*h2);//error,赋值函数重载加了delete后不能被使用
	return 0;
}

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

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

class stack_only
{
public:
	static stack_only create(int x)
	{
		return stack_only(x);
	}
private:
	int _x;
	stack_only(int x = 0):_x(x){}
};

int main()
{
	stack_only s = stack_only::create(1);
	return 0;
}

4 设计一个不能被继承的类

4.1 C++98 方式

C++98中构造函数私有化,派生类中调不到基类的构造函数。则无法继承

class base
{
private:
	base(){}
};

class derived : base
{
};

int main()
{
	derived d;//error,派生类调不到基类的构造函数,无法继承
	return 0;
}

4.2 C++11方式

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

class base final
{
private:
};

class derived : base // error,不能将final类型的类作为基类
{
};

int main()
{
	derived d;
	return 0;
}

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

单例模式是设计模式里的概念。这里简单介绍一下。
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。为什么会产生设计模式这样的东西呢?就像人类历史发展会产生兵法。最开始部落之间打仗时都是人拼人的对砍。后来春秋战国时期,七国之间经常打仗,就发现打仗也是有套路的,后来孙子就总结出了《孙子兵法》。孙子兵法也是类似。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。

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

5.1 饿汉模式

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

//单例模式
//饿汉模式
class singleton
{
public:
	static singleton* get_instance()
	{
		return _ins;
	}
}
private:
	singleton(){}//构造函数私有
	singleton(const singleton& s) = delete;//防止拷贝
	singleton& operator=(const singleton& s) = delete;
private:
	static singleton* _ins;
};
singleton* singleton::_ins = new singleton;
//在程序进入入口前就完成单例对象的初始化

使用实例:
现在要求一个类内有vector的类型存放数据,且全局仅允许有一个这样的对象,只能往这个对象里存数据。

//单例模式
//饿汉模式
class singleton
{
public:
	static singleton* get_instance()
	{
		return _ins;
	}
	void add(const string &s)
	{
		_v.push_back(s);
	}
	void print()
	{
		for (auto& i : _v)
		{
			cout << i << endl;
		}
	}
private:
	singleton(){}
	singleton(const singleton& s) = delete;
	singleton& operator=(const singleton& s) = delete;
private:
	vector<string> _v;
	static singleton* _ins;
};
singleton* singleton::_ins = new singleton;

int main()
{
	singleton::get_instance()->add("jack");
	singleton::get_instance()->add("luna");
	singleton::get_instance()->add("mike");
	singleton::get_instance()->print();

	return 0;
}

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

优点:简单
缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定。

5.2 懒汉模式

懒汉模式是第一次调用get_instance()函数时才创建对象。

class singleton
{
public:
	static singleton* get_instance()
	{
   //这一层判断是为了提高效率,第一次申请加锁保护就可以了,第二次已经不等于空了,不要保护
		if (_ins == nullptr)  
		{
			_imtx.lock();//双检查加锁
			if (_ins == nullptr)//这一层是为了线程安全问题
			{
				_ins = new singleton;
			}
			_imtx.unlock();
		}
		return _ins;
	}
	//实现一个内嵌垃圾回收类
	class GC
	{
	public:
		~GC()
		{
			del_instance();
		}
	};
	//定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象
	static GC _gc;
	static void del_instance()
	{
		_imtx.lock();
		if (_ins)
		{
			delete _ins;
			_ins = nullptr;
		}
		_imtx.unlock(); 
	}
private:
	singleton() {}
	singleton(const singleton& s) = delete;
	singleton& operator=(const singleton& s) = delete;
private:
	static singleton* _ins;
	static mutex _imtx;
};
singleton* singleton::_ins = nullptr;
mutex singleton::_imtx;
singleton::GC singleton::_gc;

优点:第一次使用实例对象时,创建对象。进程启动无负载。多个单例实例启动顺序自由控
制。
缺点:复杂

5.2.1 C++11之后懒汉模式的写法

由于C++11之后保证了静态局部对象的线程安全问题,所以代码可以简化为:文章来源地址https://www.toymoban.com/news/detail-552448.html

//懒汉模式,C++11之后的另一种写法
//C++11可以保证初始化静态对象的线程安全问题
class singleton
{
public:
	static singleton* get_instance()
	{
		//C++11之前不能这样写
		//C++11可以保证初始化静态对象的线程安全问题
		static singleton _inst;
		return &_inst;
	}
private:
	singleton() {}
	singleton(const singleton& s) = delete;
	singleton& operator=(const singleton& s) = delete;
};

到了这里,关于【C++学习笔记】特殊类设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索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日
    浏览(46)
  • C++:特殊类和单例模式

    设计一个不能被拷贝的类,通常来说方法就是把拷贝构造和赋值重载都设置为私有,这样就不能进行拷贝了 对于C++11来说,新增了delete的用法,可以直接删除这个函数,也能做到相同的效果 这是一个比较奇怪的要求,但是也有对应实现的方法: 把类的构造函数设置为私有 提

    2024年01月18日
    浏览(58)
  • 【重点:单例模式】特殊类设计

    方式如下: 将构造函数设置为私有,防止外部直接调用构造函数在栈上创建对象。 向外部提供一个获取对象的static接口,该接口在堆上创建一个对象并返回。 将拷贝构造函数设置为私有,并且只声明不实现,防止外部调用拷贝构造函数在栈上创建对象。 说明一下: 向外部

    2024年02月15日
    浏览(44)
  • 特殊类的设计(含单例模式)

    拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此 想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 C++98: 将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可。 原因: 设置成私有:如

    2024年01月23日
    浏览(50)
  • 学习笔记-设计模式-创建型模式-单例模式

    一个类只有一个实例,并提供一个全局访问此实例的点,哪怕多线程同时访问。 单例模式主要解决了 一个全局使用的类被频繁的创建和消费 的问题。 单例模式的案例场景 数据库的连接池不会反复创建 spring中一个单例模式bean的生成和使用 在我们平常的代码中需要设置全局

    2024年02月08日
    浏览(49)
  • 【C++学习笔记】特殊类设计

    C++类中只有两个拷贝的方式:拷贝构造函数和赋值运算符重载。想要设计一个不能被拷贝的类,只要想办法让类中这两种拷贝的方式不能使用即可。 因为在C++的类中,这两种拷贝的方式是默认存在的,所以需要在类中只声明不定义即可。 但是由于在用户在类外还能定义,所

    2024年02月15日
    浏览(42)
  • 【C++】特殊类的设计(只在堆、栈创建对象,单例对象)

    🌏博客主页: 主页 🔖系列专栏: C++ ❤️感谢大家点赞👍收藏⭐评论✍️ 😍期待与大家一起进步! 实现方式: 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建 实现方法:

    2024年02月06日
    浏览(47)
  • 【C++】设计模式-单例模式

    目录 一、单例模式 单例模式的三个要点 针对上述三要点的解决方案 常用的两类单例模式  二、懒汉模式实现 1.基本实现 2.锁+静态成员析构单例 3.双层检查锁定优化 4.双层检查锁定+智能指针 三、饿汉模式实现 1.基础实现 2.嵌套内部类解决内存泄漏 3.智能指针解决内存泄漏

    2024年02月16日
    浏览(38)
  • C++设计模式代码--单例模式

    参考:5. 单例模式(Singleton) (yuque.com) 1、什么是单例模式 保证一个类只有一个实例,并提供一个访问该实例的全局节点; 2、什么情况下需要单例模式 某个类的对象在软件运行之初就创建,并且在软件的很多地方都需要读写这个类的信息;使用单例模式的话,类对象就只要

    2024年02月03日
    浏览(54)
  • C++设计模式:单例模式(十)

    1、单例设计模式 单例设计模式,使用的频率比较高,整个项目中某个特殊的类对象只能创建一个 并且该类只对外暴露一个public方法用来获得这个对象。 单例设计模式又分懒汉式和饿汉式,同时对于懒汉式在多线程并发的情况下存在线程安全问题 饿汉式:类加载的准备阶段

    2024年04月14日
    浏览(46)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包