【C++】特殊类设计

发布时间:2026/9/1 9:38:12
【C++】特殊类设计 目录1.请设计一个类不能被拷贝2.请设计一个类只能在堆上创建对象3.请设计一个类只能在栈上创建对象4.请设计一个类不能被继承5.请设计一个类只能创建一个对象(单例模式)1.请设计一个类不能被拷贝拷贝只会发生在两个场景中拷贝构造函数以及赋值运算符重载因此想要让一个类禁止拷贝只需让该类不能调用拷贝构造函数以及赋值运算符重载即可C98方式将拷贝构造函数与赋值运算符重载只声明不定义并且将其访问权限设置为私有即可。class CopyBan { // ... private: CopyBan(const CopyBan); CopyBan operator(const CopyBan); //... };原因1. 设置成私有如果只声明而没有设置成private用户自己如果在类外定义了就不能禁止拷贝了2. 只声明不定义不定义是因为该函数根本不会调用定义了其实也没有什么意义不写反而还简单而且如果定义了就不会防止成员函数内部拷贝了。C11方式C11扩展delete的用法delete除了释放new申请的资源外如果在默认成员函数后跟上delete表示让编译器删除掉该默认成员函数。class CopyBan { // ... CopyBan(const CopyBan)delete; CopyBan operator(const CopyBan)delete; //... };2. 请设计一个类只能在堆上创建对象实现方式11. 将类的构造函数私有拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。2. 提供一个静态的成员函数在该静态成员函数中完成堆对象的创建为什么需要静态的成员函数调用 CreateObject 需要一个对象而 CreateObject 的功能就是创建对象如果将 CreateObject 声明为静态就不需要用对象来调用可以用 HeapOnly::CreateObject() 来调用。class HeapOnly { public: static HeapOnly* CreateObject() { return new HeapOnly; } private: HeapOnly() {} // C98 // 1.只声明,不实现。因为实现可能会很麻烦而你本身不需要 // 2.声明成私有 HeapOnly(const HeapOnly) // or // C11 HeapOnly(const HeapOnly) delete; };实现方式2将析构函数声明为私有在栈和静态区上创建的对象无法自动调用析构函数而报错在堆创建的对象不会自动调用析构函数在类中声明一个 Destroy 函数来析构对象。class HeapOnly { public: void Destroy() { delete this; } private: ~HeapOnly() { //... } }; int main() { HeapOnly* p new HeapOnly; p-Destroy(); return 0; }3.请设计一个类只能在栈上创建对象同上将构造函数私有化然后设计静态方法创建对象返回即可class StackOnly { public: static StackOnly CreateObj() { return StackOnly(); } // 禁掉operator new可以把下面用new 调用拷贝构造申请对象给禁掉 // StackOnly obj StackOnly::CreateObj(); // StackOnly* ptr3 new StackOnly(obj); // new 调用的是拷贝构造 // 创建成功 error void* operator new(size_t size) delete; void operator delete(void* p) delete; private: StackOnly() :_a(0) {} private: int _a; };4. 请设计一个类不能被继承C98方式// C98中构造函数私有化派生类中调不到基类的构造函数。则无法继承 class NonInherit { public: static NonInherit GetInstance() { return NonInherit(); } private: NonInherit() {} };C11方式final关键字final修饰类表示该类不能被继承。class A final { // .... };5. 请设计一个类只能创建一个对象(单例模式)设计模式设计模式Design Pattern是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。使用设计模式的目的为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化设计模式是软件工程的基石脉络如同大厦的结构一样。单例模式一个类只能创建一个对象即单例模式该模式可以保证系统中该类只有一个实例并提供一个访问它的全局访问点该实例被所有程序模块共享。比如在某个服务器程序中该服务器的配置信息存放在一个文件中这些配置数据由一个单例对象统一读取然后服务进程中的其他对象再通过这个单例对象获取这些配置信息这种方式简化了在复杂环境下的配置管理。单例模式有两种实现模式饿汉模式就是说不管你将来用不用程序启动时就创建一个唯一的实例对象1、构造函数、拷贝构造、赋值重载私有2、在类中定义一个同类的静态对象3、提供访问静态对象的接口4、在程序入口之前就完成单例对象的初始化优点1、实现简单。2、如果这个单例对象在多线程高并发环境下频繁使用性能要求较高那么显然使用饿汉模式来避免资源竞争提高响应速度更好。缺点1、如果单例对象较大可能会导致进程启动慢可能不知道是程序挂了还是正在启动且影响调试的效率因为静态的对象在程序一加载在 mian 函数之前就定义好了。2、如果有多个单例类对象则它们实例顺序不确定如果 A 的初始化依赖 B这时可能出现错误// 饿汉模式 // 优点简单 // 缺点可能会导致进程启动慢且如果有多个单例类对象实例启动顺序不确定。 class Singleton { public: static Singleton* GetInstance() { return m_instance; } private: // 构造函数私有 Singleton() {}; // C98 防拷贝 Singleton(Singleton const); Singleton operator(Singleton const); // or // C11 Singleton(Singleton const) delete; Singleton operator(Singleton const) delete; // 在类中声明一个同类的对象这个对象只能通过函数获取 static Singleton m_instance; // 不能声明为非静态的否则会无限套娃 }; Singleton Singleton::m_instance; // 在程序入口之前就完成单例对象的初始化 // m_instance 定义在类里它可以调用构造函数懒汉模式如果单例对象构造十分耗时或者占用很多资源比如加载插件 初始化网络连接读取文件等等而有可能该对象程序运行时不会用到这种情况使用懒汉模式延迟加载更好。class Singleton { public: static Singleton* GetInstance() { if(p_instance nullptr) { p_instance new Singleton; } return *p_instance; } // 一般单例不用释放。 // 特殊场景1、中途需要显式释放 // 2、释放单例或程序结束时需要做一些特殊处理如数据写到文件 static void DelInstance() { if (_psinst) { delete _psinst; _psinst nullptr; } } ~Singleton() { // 数据写到文件中 } private: // 构造函数私有 Singleton() {}; // C98 防拷贝 Singleton(Singleton const); Singleton operator(Singleton const); // or // C11 Singleton(Singleton const) delete; Singleton operator(Singleton const) delete; static Singleton* p_instance nullptr; };如果有多个单例对象这些单例对象都要显式调用 DelInstance() 来完成某个功能但由于程序的出口也有很多要保证在程序退出时单例对象都要显式调用 DelInstance() 难免有疏忽可以考虑用一个类来管理这些单例对象的 DelInstance()类似于智能指针。class GC { public: ~GC() { lazy::Singleton::DelInstance(); } }; GC gc;可以把 GC 类定义为单例类的内部类在单例类中定义一个 GC 的静态对象在类外初始化它的作用是确保在退出程序时调用 DelInstance()C11 之后的懒汉模式上面的懒汉模式是 C11 之前的懒汉模式的写法在 C11 之后有一种更简单的写法class Singleton { public: static Singleton GetInstance() { static Singleton inst; return inst; } private: // 构造函数私有 Singleton() {}; // C98 防拷贝 Singleton(Singleton const); Singleton operator(Singleton const); // or // C11 Singleton(Singleton const) delete; Singleton operator(Singleton const) delete; };上面的懒汉模式在 C11 之后才能使用因为 C11 之后才保证如果多个线程同时试图初始化一个静态局部变量则初始化过程是线程安全的且仅发生一次。