【C++】特殊类设计

目录

设计一个类不能被拷贝

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

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

设计一个类,不能被继承

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


设计一个类不能被拷贝

C++98的做法:将拷贝构造和赋值重载只声明不实现,并设为私有,为什么要声明,因为它们是默认成员函数,我们不写编译器会自动生成

C++11做法:直接用delete


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

方法一:析构函数私有

这时候就无法直接创建对象,但是可以new对象,因为析构函数私有,这时创建对象没办法自动调用析构,怎么释放呢,许愿写一个公有的释放函数通过new返回的指针去调用释放函数

cpp 复制代码
class HeapOnly
{
private:
	~HeapOnly()
	{
		cout << "~" << endl;
	}
};

int main()
{
	HeapOnly ho; //无法自动调用析构
	HeapOnly* ptr = new HeapOnly;
	delete ptr; //无法调用析构

	return 0;
}

静态公有释放函数

cpp 复制代码
class HeapOnly
{
public:
	static void Destroy(HeapOnly* ptr)
	{
		delete ptr;
	}

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

int main()
{
	//HeapOnly ho; //无法自动调用析构
	HeapOnly* ptr = new HeapOnly;
	//delete ptr; //无法调用析构
	HeapOnly::Destroy(ptr);
	return 0;
}

更好的写法,直接delete this

cpp 复制代码
class HeapOnly
{
public:
	void Destroy()
	{
		delete this;
	}

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

int main()
{
	HeapOnly* ptr = new HeapOnly;
	ptr->Destroy();
	return 0;
}

方法二:构造函数私有

这时无论是直接创建对象还是new对象都不行了,

cpp 复制代码
class HeapOnly
{
public:


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

int main()
{
	HeapOnly h1;
	HeapOnly* ptr = new HeapOnly;

	return 0;
}

需要写一个公有函数来创建

但是这里却无法调用Creat(),因为这里调用这个函数得先有对象,但是我调用这个函数的原因就是我要创建对象,这里就可以用静态来解决

cpp 复制代码
class HeapOnly
{
public:
	HeapOnly* Creat()
	{
		return new HeapOnly;
	}

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

int main()
{
	HeapOnly* ptr = Creat(); //调用不了
	return 0;
}
cpp 复制代码
class HeapOnly
{
public:
	static HeapOnly* Creat()
	{
		return new HeapOnly;
	}

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

int main()
{
	HeapOnly* ptr = HeapOnly::Creat();
	return 0;
}

有一个缺陷就是通过拷贝构造也能在栈上创建,所以要把拷贝构造给禁了


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

先把构造函数私有,然后写一个静态的公有创建函数

cpp 复制代码
class StackOnly
{
public:
	static StackOnly Creat()
	{
		StackOnly s1;
		return s1;
	}

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

int main()
{
	StackOnly s = StackOnly::Creat();
	return 0;
}

有一个缺陷,就是可以通过拷贝构造创建,这里如果单纯禁掉拷贝构造的话,那个公有函数的传值返回就无法实现,

new分为operator new 和 调用拷贝构造,operator new是全局的,但如果类内写了一个就会调类内的,new这个对象的时候就会调类内的不会调全局的,所以我们可以把operator new禁掉,相当于间接禁掉new

cpp 复制代码
StackOnly* ptr = new StackOnly(s);

设计一个类,不能被继承

C++98做法:构造函数私有,派生类就调不到基类的构造函数则无法继承

C++11做法:final表示该类不能被继承

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

单例模式是一种设计模式,设计模式是代码设计的经验总结

单例是指全局只有一个唯一的实例对象,单例模式分为饿汉模式和懒汉模式,饿汉:提前创建好,main函数启动时创建好实例对象,懒汉:第一次用的时候再创建

饿汉

先把构造函数和拷贝构造私有,创建一个A类型的静态成员,因为静态成员不在对象里面,是存在静态区的,类内声明类外定义,然后提供一个该成员地址的静态公有函数,通过这个函数获取到这一个唯一对象的地址。

cpp 复制代码
class A
{
public:
	static A* GetInstance()
	{
		return &_inst;
	}

	void print()
	{

	}

private:
	A()
	{}
	A(const A& aa) = delete;
	A& operator=(const A& aa) = delete;

	static A _inst;
};

A A::_inst;

int main()
{
	A::GetInstance()->print();
	return 0;
}

饿汉模式的优点:相比懒汉实现简单,缺点:1. 可能会导致进程启动慢,2. 无法控制单例先后启动顺序

懒汉

在饿汉的基础上把静态成员的类型变成指针,在类外定义为空,

获取对象的函数也需要修改

cpp 复制代码
	static B* GetInstance()
	{
		if (_Binst == nullptr)
		{
			_Binst = new B;
		}
		return _Binst;
	}
cpp 复制代码
int main()
{
	B::GetInstance()->print();
	return 0;
}

析构问题

new的懒汉对象一般不需要释放,进程正常结束会释放,但有时候我们需要在析构做点事情比如持久化处理,想要让进程结束时调用析构,首先弄一个gc内部类,创建一个gc静态对象,在main函数结束它会调用析构函数,

cpp 复制代码
class B
{
public:
	static B* GetInstance()
	{
		if (_Binst == nullptr)
		{
			_Binst = new B;
		}
		return _Binst;
	}

	void print()
	{

	}

	static void DelInstance()
	{
		if (_Binst)
		{
			delete _Binst;
			_Binst = nullptr;
		}
	}

private:
	B()
	{}
	~B()
	{
		cout << "hhh" << endl;
	}
	B(const B& aa) = delete;
	B& operator=(const B& aa) = delete;

	static B* _Binst;

	class gc
	{
	public:
		~gc()
		{
			DelInstance();
		}
	};

	static gc _gc;
};

B* B::_Binst = nullptr;
B::gc B::_gc;
相关推荐
DYS_房东的猫16 分钟前
《 C++ 零基础入门教程》第3章:结构体与类 —— 用面向对象组织代码
开发语言·c++
郑泰科技22 分钟前
快速地图匹配(FMM)的开源工具与代码示例
c++·windows·python·交通物流
CoderCodingNo22 分钟前
【GESP】C++五级练习(贪心思想考点) luogu-P1115 最大子段和
开发语言·c++·算法
Q741_14722 分钟前
C++ 队列 宽度优先搜索 BFS 力扣 429. N 叉树的层序遍历 每日一题
c++·算法·leetcode·bfs·宽度优先
txinyu的博客25 分钟前
make_shraed & make_unique 替代了new ? 什么场景使用new
开发语言·c++·算法
一只小bit26 分钟前
Qt 重要控件:多元素控件、容器类控件及布局管理器
前端·c++·qt
微露清风34 分钟前
系统学习C++-第二十一讲-用哈希表封装 myunordered_map 和 myunordered_set
c++·学习·散列表
恋爱绝缘体110 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit
Z1Jxxx11 小时前
加密算法加密算法
开发语言·c++·算法
乌萨奇也要立志学C++11 小时前
【洛谷】递归初阶 三道经典递归算法题(汉诺塔 / 占卜 DIY/FBI 树)详解
数据结构·c++·算法