当前位置: 首页 > news >正文

【C++】特殊类设计

特殊类设计

  • 1.设计类:不能被拷贝
  • 2.设计类:不能被继承
  • 3.设计类:只能在堆上创建对象
  • 4.设计类:只能在栈上创建对象
  • 5.设计类:只能创建一个对象(单例模式)

本节重点:

  • 掌握特殊类的设计方式

1.设计类:不能被拷贝

// C++98私有化
class Copy
{
private:
	Copy(const Copy&);
	Copy& operator=(const Copy&);
};
// C++11关键字delete
class Copy
{
public:
	Copy(const Copy&) = delete;
	Copy& operator=(const Copy&) = delete;
};

2.设计类:不能被继承

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

private:
	NoInherit()
	{}
};
// C++11关键字fianl
class NoInherit final
{
	// ...
};

3.设计类:只能在堆上创建对象

class HeapOnly
{
public:
	static HeapOnly* CreateObj()
	{
		return new HeapOnly();
	}
	
	// 禁用: 拷贝构造和拷贝赋值
	HeapOnly(const HeapOnly&) = delete;
	HeapOnly& operator=(const HeapOnly&) = delete;

private:
	// 默认构造私有化
	HeapOnly()
	{}
};

int main()
{
	// HeapOnly obj1;
	// static HeapOnly obj2;
	// HeapOnly *obj3 = new HeapOnly();

	HeapOnly* obj4 = HeapOnly::CreateObj();

	// HeapOnly obj5(*obj4);
	// HeapOnly obj6 = *obj4;

	delete obj4;

	return 0;
}
class HeapOnly
{
public:
	void Delete()
	{
		delete this;
	}
private:
	// 析构函数私有化
	~HeapOnly()
	{}
};

int main()
{
	// 程序结束调用析构函数, 由于私有化, 无法创建对象 
	// HeapOnly obj1;
	// static HeapOnly obj2;

	// 可以在堆上创建对象, 但是调用delete存在问题(delete: 先调用析构函数, 再释放空间)
	// HeapOnly* obj3 = new HeapOnly();
	// delete obj3;

	HeapOnly *obj4 = new HeapOnly();
	obj4->Delete();

	return 0;
}

4.设计类:只能在栈上创建对象

class StackOnly
{
public:
	static StackOnly CreateObj()
	{
		return StackOnly();
	}

	void* operator new(size_t) = delete;
	void operator delete(void*) = delete;

private:
	StackOnly()
	{}
};

int main()
{
	// StackOnly obj1;
	// static StackOnly obj2;
	// StackOnly* obj3 = new StackOnly();

	// 传值返回需要拷贝构造
	StackOnly obj4 = StackOnly::CreateObj();
	StackOnly obj5(obj4);
	StackOnly obj6 = obj4;

	// 但是用拷贝构造创建堆区对象: 于是可以禁用new
	// StackOnly* obj7 = new StackOnly(obj4);

	// 问题: 静态区创建对象
	static StackOnly obj8(obj4);

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

	// 禁用拷贝构造, 打开移动构造
	StackOnly(StackOnly&&){}
	StackOnly(const StackOnly&) = delete;

private:
	StackOnly()
	{}
};

int main()
{
	// StackOnly obj1;
	// static StackOnly obj2;
	// StackOnly* obj3 = new StackOnly();

	// 此时采用: 移动构造
	StackOnly obj4 = StackOnly::CreateObj();

	// StackOnly obj5(obj4);
	// StackOnly obj6 = obj4;
	// StackOnly* obj7 = new StackOnly(obj4);
	// static StackOnly obj8(obj4);

	// 问题: 移动构造创建对象
	static StackOnly obj8(move(obj4));
	StackOnly* obj9 = new StackOnly(move(obj4));

	return 0;
}

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

  • 设计模式:反复使用,多数人知晓、经过分类的、代码设计经验的总结。
  • 单例模式:一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
  • 迭代器模式、适配器模式、单例模式、策略模式、观察者模式、工厂模式、装饰器模式等…

单例模式有两种实现模式:饿汉模式和懒汉模式

// 饿汉模式存在问题
// 1. 多个饿汉模式的单例,某个对象初始化内容较多(读文件),会导致程序启动慢
// 2. A和B两个饿汉,对象初始化存在依赖关系,要求A先初始化,B再初始化,无法保证
class InfoMar
{
public:
	static InfoMar& GetInstance()
	{
		return _ins;
	}

private:
	InfoMar()
	{
		cout << "ip:" << _ip << endl;
		cout << "port: " << _port << endl;
	}

	// 禁用: 拷贝构造和拷贝赋值
	InfoMar(const InfoMar&) = delete;
	InfoMar& operator=(const InfoMar&) = delete;

private:
	string _ip = "127.0.0.1";
	int _port = 8080;
	
	// 静态对象与普通对象不同: 不在类中, 而是在静态区, 类域的限制
	static InfoMar _ins;
};

// 静态成员: 类内声明, 类外定义
InfoMar InfoMar::_ins;

int main()
{
	// 程序运行在该行: 静态对象就被创建好了
	InfoMar::GetInstance();

	return 0;
}
// 懒汉模式: 解决饿汉模式的两个问题
class InfoMar
{
public:
	static InfoMar& GetInstance()
	{
		// 第一次调用时创建单例对象
		// 存在线程安全问题
		if (_pins == nullptr)
		{
			_pins = new InfoMar;
		}
		return *_pins;
	}

	static void DelInstance()
	{
		delete _pins;
		_pins = nullptr;
	}

private:
	InfoMar()
	{
		cout << "ip:" << _ip << endl;
		cout << "port: " << _port << endl;
	}

	// 禁用: 拷贝构造和拷贝赋值
	InfoMar(const InfoMar&) = delete;
	InfoMar& operator=(const InfoMar&) = delete;

private:
	string _ip = "127.0.0.1";
	int _port = 8080;
	
	static InfoMar* _pins;
};

InfoMar* InfoMar::_pins = nullptr;

int main()
{
	InfoMar::GetInstance();

	return 0;
}

// 懒汉模式2: 推荐
class InfoMar
{
public:
	static InfoMar& GetInstance()
	{
		// 局部静态: 再第一次调用时创建单例对象
		// C++11之后
		static InfoMar ins;
		return ins;
	}

private:
	InfoMar()
	{
		cout << "ip:" << _ip << endl;
		cout << "port: " << _port << endl;
	}

	// 禁用: 拷贝构造和拷贝赋值
	InfoMar(const InfoMar&) = delete;
	InfoMar& operator=(const InfoMar&) = delete;

private:
	string _ip = "127.0.0.1";
	int _port = 8080;
};

int main()
{
	InfoMar::GetInstance();

	return 0;
}

相关文章:

  • 【CXX】6.4 CxxString — std::string
  • 第十七:go 反射
  • Spring Boot中@Valid 与 @Validated 注解的详解
  • macOS 终端优化
  • 使用DeepSeek+蓝耘快速设计网页简易版《我的世界》小游戏
  • 从0到1:JavaScript小白进阶之路
  • mapbox-gl的Popup的使用详解
  • 旋转位置编码(3)
  • HarmonyOS
  • Spring Boot 项目中使用责任链模式实现复杂接口解耦和动态编排(带示例)
  • 前端技术百宝箱
  • Tweak Power:全方位电脑系统优化的高效工具
  • MySQL 与 MongoDB 的区别
  • CAN总线协议攻防实战:从漏洞分析到攻击模拟
  • 衣联网的商品列表页面结构是怎样的?
  • 设计基于锁的并发数据结构_第六章_《C++并发编程实战》笔记
  • 新一代开源数字供应链安全审查与治理平台:悬镜源鉴SCA
  • 版本控制泄露源码 .svn
  • 机器学习数学基础:45.多重响应分析
  • 鸿蒙应用开发-轻松获取http网络请求
  • 墨海军训练舰在纽约撞桥,墨总统:对遇难者表示悲痛,将跟进调查
  • 外媒:哈马斯一名高级指挥官尸体被发现,系辛瓦尔弟弟
  • 公示资费套餐、规范营销行为,今年信息通信行业将办好这十件实事
  • 朱雀二号改进型遥二运载火箭发射成功
  • 体坛联播|热刺追平单赛季输球纪录,世俱杯或创收20亿美元
  • 时隔三年,俄乌直接谈判重启