当前位置:首页 » 《随便一记》 » 正文

C++特殊类设计

6 人参与  2023年04月04日 17:03  分类 : 《随便一记》  评论

点击全文阅读


目录

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

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

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

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

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


 

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

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

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

原因:
1. 设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,就不能禁止拷贝了
2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不会防止成员函数内部拷贝了。

C++11
C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上
=delete,表示让编译器删除掉该默认成员函数。

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

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

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

class HeapOnly  {  public:    static HeapOnly* CreateObject()  {       return new HeapOnly;   }private:    HeapOnly() {}   // C++98  // 1.只声明,不实现。因为实现可能会很麻烦,而你本身不需要// 2.声明成私有  HeapOnly(const HeapOnly&);   // or     // C++11    HeapOnly(const HeapOnly&) = delete;};

 方法2:将析构函数和拷贝构造函数设置为私有

class HeapOnly{public:HeapOnly(){}void Destroy(){this->~HeapOnly();}private:~HeapOnly(){}HeapOnly(const HeapOnly&) = delete;};int main(){//HeapOnly hp1;HeapOnly* php = new HeapOnly;php->Destroy();return 0;}

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

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

class StackOnly{public:static StackOnly CreateObj(){return StackOnly();}// 禁掉operator new可以把下面用new 调用拷贝构造申请对象给禁掉// StackOnly obj = StackOnly::CreateObj();// StackOnly* ptr3 = new StackOnly(obj);void* operator new(size_t size) = delete;void operator delete(void* p) = delete;private:StackOnly():_a(0){}private:int _a;};int main(){StackOnly st = StackOnly::CreateObj();//无法禁掉在静态区上创建的对象static StackOnly st1 = StackOnly::CreateObj();return 0;}

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

C++98方式

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

C++11方法
final关键字,final修饰类,表示该类不能被继承。

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

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

设计模式:
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的
总结。为什么会产生设计模式这样的东西呢?就像人类历史发展会产生兵法。最开始部落之间打
仗时都是人拼人的对砍。后来春秋战国时期,七国之间经常打仗,就发现打仗也是有套路的,后
来孙子就总结出了《孙子兵法》。孙子兵法也是类似。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模
式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
单例模式:
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个
访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置
信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再
通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
单例模式有两种实现模式:
饿汉模式
就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象。

// 单例模式的类:全局只有一个唯一对象// 饿汉模式:一开始(main函数之前)就创建对象// 缺点:1、单例对象初始化时数据太多,导致启动慢//      2、多个单例类有初始化依赖关系,饿汉模式无法控制class Singleton{public:static Singleton& GetInstance(){return m_instance;}void Print(){cout << "Singleton Print()" << endl;}private:// 构造函数私有Singleton() {};// C++98 防拷贝Singleton(Singleton const&) = delete;Singleton& operator=(Singleton const&) = delete;static Singleton m_instance;};Singleton Singleton::m_instance;// 在程序入口之前就完成单例对象的初始化int main(){Singleton::GetInstance().Print();return 0;}

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

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

实现方式1:

// 懒汉模式:第一次获取单例对象的时候创建对象// 1、对象在main函数之后才会创建,不会影响启动顺序// 2、可以主动控制创建顺序class InfoSingleton{public:// 多个线程一起调用GetInstance,存在线程安全的风险,//static InfoSingleton& GetInstance()//{//// 第一次获取单例对象的时候创建对象//// 双检查加锁//if (_psins == nullptr)  // 对象new出来以后,避免每次都加锁的检查,提高性能//{//// t1  t2//_smtx.lock();//try-catch解决方式不太好,可以用RAII管理锁//try//{//if (_psins == nullptr)  // 保证线程安全且只new一次//{//_psins = new InfoSingleton;//}//}//catch (...)//{//_smtx.unlock();//throw;//}//_smtx.unlock();//}//return *_psins;//}static InfoSingleton& GetInstance(){// 第一次获取单例对象的时候创建对象// 双检查加锁if (_psins == nullptr)  // 对象new出来以后,避免每次都加锁的检查,提高性能{// t1  t2// 可以使用自己模拟实现的//LockGuard<mutex> lock(_smtx);//也可以使用库中的std::lock_guard<mutex> lock(_smtx);if (_psins == nullptr)  // 保证线程安全且只new一次{_psins = new InfoSingleton;}}return *_psins;}// 一般单例对象不需要考虑释放// 单例对象不用时,必须手动处理,一些资源需要保存// 可以手动调用主动回收// 也可以让他自己在程序结束时,自动回收static void DelInstance(){// 保存数据到文件// ...std::lock_guard<mutex> lock(_smtx);if (_psins){delete _psins;_psins = nullptr;}}// 也可以让他自己在程序结束时,自动回收class GC{public:~GC(){if (_psins){cout << "~GC()" << endl;DelInstance();}}};void Insert(string name, int salary){_info[name] = salary;}void Print(){for (auto kv : _info){cout << kv.first << ":" << kv.second << endl;}cout << 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 GC _gc;};InfoSingleton* InfoSingleton::_psins = nullptr;mutex InfoSingleton::_smtx;InfoSingleton::GC InfoSingleton::_gc;int main(){InfoSingleton::GetInstance().Insert("张三", 10000);InfoSingleton& infosl = InfoSingleton::GetInstance();infosl.Insert("李四", 15000);infosl.Insert("赵六", 12000);infosl.Insert("王五", 8000);infosl.Print();InfoSingleton::GetInstance().Insert("张三", 13000);InfoSingleton::GetInstance().Print();infosl.Print();//InfoSingleton::DelInstance();return 0;}

实现方式2:

//1、是懒汉。 因为静态的局部变量是在main函数之后才创建初始化的//2、C++11之前,这里是不能保证sinst的初始化是线程安全的。//3、C++11之后,可以。class InfoSingleton{public:static InfoSingleton& GetInstance(){static InfoSingleton sinst;return sinst;}void Insert(string name, int salary){_info[name] = salary;}void Print(){for (auto kv : _info){cout << kv.first << ":" << kv.second << endl;}cout << endl;}private:InfoSingleton(){cout << "InfoSingleton()" << endl;}InfoSingleton(const InfoSingleton& info) = delete;InfoSingleton& operator=(const InfoSingleton& info) = delete;map<string, int> _info;// ...};int main(){InfoSingleton::GetInstance().Insert("张三", 10000);InfoSingleton& infosl = InfoSingleton::GetInstance();infosl.Insert("李四", 15000);infosl.Insert("赵六", 12000);infosl.Insert("王五", 8000);infosl.Print();InfoSingleton::GetInstance().Insert("张三", 13000);InfoSingleton::GetInstance().Print();infosl.Print();//InfoSingleton::DelInstance();return 0;}


点击全文阅读


本文链接:http://zhangshiyu.com/post/58327.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1