欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > 特殊类的设计/单例模式

特殊类的设计/单例模式

2025/4/2 2:56:45 来源:https://blog.csdn.net/popingcat/article/details/146771380  浏览:    关键词:特殊类的设计/单例模式

1.设计一个类不能拷贝

class NotCopy
{//只声明不实现!
public:
private:NotCopy(const NotCopy&);NotCopy& operator=(const NotCopy&);//还有一种方法就是,c++11里面的加关键字delete
};

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

class HeapOnly
{
public://在这里我需要解释的是,肯定会有疑问为什么要用静态成员函数!//首先如果不用静态成员,普通函数放在类里面,如果在类外面想要被调用,首先得先实例化一个对象,然后才能调用!//然后因为我们为了实现在堆上创建对象,所以我们把构造函数和析构函数都进行了私有化,所以我们直接在栈上实例化对象是不可能了//因此我们没有了对象,现在要调用函数只能通过静态函数,因为静态函数它不需要通过对象调用,它自己就是可以看做类本身,加上作用域就可以了static HeapOnly* creat(){return new HeapOnly;}//静态函数属于类本身,不属于类的某个具体对象实例 ,它可以在不依赖对象实例的情况下被调用static void destory(HeapOnly* ptr){delete ptr;}HeapOnly(const HeapOnly& hp) = delete;//这里把拷贝构造禁止掉!
private://方案一,析构函数私有化!HeapOnly() {};~HeapOnly(){}};

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

class StackOnly
{
public:static StackOnly creat(){StackOnly obj;//这是在栈上面!return obj;}//如果你有实现一个专属类的operator new这样,它会优先调用自己的,不会去用库里面的!/*void* operator new(size_t size){cout << "void* operator new" << endl;return malloc(size);}*///所以通过上面这种操作,其实可以在自己的类里面把operator new给ban掉void* operator new(size_t size) = delete;/*~StackOnly();*/private:StackOnly(){cout << "stackonly" << endl;}
};

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

class NotInherit
{//方案一:构造函数私有化!// 因为当你父类构造函数私有化的时候,// 你子类创建对象的时候会初始化列表的时候先要调用父类构造函数初始化父类的变量!//方案二就是给类加final
private:NotInherit(){}
};

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

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

方案一:饿汉模式-把对象提前创建好(程序启动时:main函数启动时),饿了直接吃!
想一想什么对象,可以在main函数前创建好,答案肯定可以想到全局变量!
优点:实现简单
缺点:进程启动慢,如果两个单例启动又先后顺序,饿汉模式无法控制!

class A
{
public:static A* getInstance(){return &inst;}void add(const string& k,const string&v){dict[k] = v;}void print(){for (auto e : dict){cout << e.first <<": " << e.second << endl;}cout << endl;}private:A(){}map<string, string> dict;int _n = 0;//把拷贝构造和赋值都禁掉,防止出现多个单例!A(const A& aa) = delete;A& operator=(const A& aa) = delete;static A inst;//这里是声明,静态成员变量要在类外面定义!
};A A::inst;
//A inst;//全局!它是会有很多缺陷的,当你把全局放在.h里面多个cpp都能用到它,会出现连接错误的!

方案二:懒汉模式-第一次用的时候再创建(现吃现做)
//new的懒汉对象一般不需要释放 进程自然结束,会自动释放资源;这里的释放资源其实是解除页表式的释放资源!

class B
{
public:static B* getInstance(){if (inst == nullptr){inst = new B;//如果写成 new B* ,得到的指针指向的是一个存储 B 类指针的空间,// 并非实际的 B 类对象,后续无法通过 inst 正确操作期望的单例对象。}return inst;}void add(const string& k, const string& v){dict[k] = v;}void print(){for (auto e : dict){cout << e.first << ": " << e.second << endl;}cout << endl;}//如果你需要手动释放资源你就调用下面的函数!,给它设置成静态全局变量是因为可以让整个类都能访问到!static void DelInstance(){if (inst){delete inst;inst = nullptr;}}
private:B() {}map<string, string> dict;int _n = 0;//把拷贝构造和赋值都禁掉,防止出现多个单例!B(const B& bb) = delete;B& operator=(const B& bb) = delete;static B* inst;//这里是声明,静态成员变量要在类外面定义!//内部类,是外部类的的友元class del{public:~del(){DelInstance();}};static del D;//之所以有静态全局对象是因为,要触发del的析构函数,//而为什么用静态是因为只有静态成员其实是main程序结束后,系统开始清理资源时才会被释放
};B* B::inst=nullptr;
B::del B:: D;void test()
{/*StackOnly obj= StackOnly::creat();*///虽然禁止了下面这个玩法,但是/*int* _ptr = new int;StackOnly* ptr = _ptr;*//*StackOnly* ptr = new StackOnly(obj);*///这种情况也是能在堆上创建的!,所以解决它的办法就是去弄一个自己的类new//不管你调用什么函数,得先单例出来一个对象才可以!B::getInstance()->add("sort", "排序");B::getInstance()->add("interator", "迭代器");/*A::print();错误写法!*/B::getInstance()->print();//为了防止多个单例出现所以要禁掉拷贝构造!
}

单例模式细节(未完结)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词