C++设计的禁忌与救赎:特殊类设计

📅 发布时间:2026/7/16 14:47:24 👁️ 浏览次数:
C++设计的禁忌与救赎:特殊类设计
.请设计一个类不能被拷贝涉及拷贝的只有拷贝构造和赋值重载把这些禁用了就行了代码语言javascriptAI代码解释class CopyBan { // ... private: CopyBan(const CopyBan); CopyBan operator(const CopyBan); //... };对于C98直接设置为私有即可这样类外就无法访问了只声明不定义不定义是因为该函数根本不会调用定义了其实也没有什么意义不写反而还简单而且如果定义了就不会防止成员函数内部拷贝了代码语言javascriptAI代码解释class CopyBan { // ... CopyBan(const CopyBan) delete; CopyBan operator(const CopyBan) delete; //... };对于C11直接在默认成员函数后跟上 delete表示让编译器删除掉该默认成员函数2.请设计一个类只能在堆上创建对象代码语言javascriptAI代码解释class HeapOnly { public: static HeapOnly* CreateObject() { return new HeapOnly; } private: HeapOnly() {} // C98 // 1.只声明,不实现。因为实现可能会很麻烦而你本身不需要 // 2.声明成私有 HeapOnly(const HeapOnly); // or // C11 HeapOnly(const HeapOnly) delete; };创建对象需要构造函数所以首先把构造函数给禁用了还注意应该禁止拷贝构造防止再创建因为类内能调用构造函数所以创建一个public函数提供接口在构造函数被私有化的情况下静态方法是唯一能够访问私有构造函数并创建对象的途径静态方法属于类本身而非类的某个实例因此无需创建对象即可调用例如HeapOnly::CreateObject()可直接通过类名调用3.请设计一个类只能在栈上创建对象代码语言javascriptAI代码解释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; };因为堆上创建销毁需要通过new和delete之前又学过new - operator new 构造函数delete - operator delete 析构函数所以直接将这些禁掉就好了4.请设计一个类不能被继承代码语言javascriptAI代码解释class NonInherit { public: static NonInherit GetInstance() { return NonInherit(); } private: NonInherit() {} };C98中构造函数私有化派生类中调不到基类的构造函数则无法继承代码语言javascriptAI代码解释class A final { // .... };final关键字final修饰类表示该类不能被继承5.请设计一个类只能创建一个对象(单例模式)单例模式一个类只能创建一个对象即单例模式该模式可以保证系统中该类只有一个实例并提供一个访问它的全局访问点该实例被所有程序模块共享。比如在某个服务器程序中该服务器的配置信息存放在一个文件中这些配置数据由一个单例对象统一读取然后服务进程中的其他对象再通过这个单例对象获取这些配置信息这种方式简化了在复杂环境下的配置管理以下是单例模式的两种实现模式饿汉模式代码语言javascriptAI代码解释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; // 在程序入口之前就完成单例对象的初始化静态变量属于类而非对象程序运行期间仅存在一份实例且在程序入口main()前初始化static Singleton m_instance;是声明Singleton Singleton::m_instance;是定义饿汉模式在程序启动时或类加载时立即创建单例实例若实例的初始化逻辑复杂如 读取大文件 / 配置如数据库连接、配置文件 网络请求初始化远程服务连接 复杂计算预加载数据字典、缓存构建 这些操作会阻塞进程的启动流程导致启动时间明显增加全局静态对象的初始化顺序问题在C中多个全局静态对象的初始化顺序是未定义的由编译器和链接器决定若某个饿汉单例A依赖另一个全局对象B而B的初始化顺序在A之后会导致A初始化时访问未初始化的B引发逻辑错误或崩溃这类问题难以调试且会间接增加启动阶段的异常处理开销懒汉模式代码语言javascriptAI代码解释class Singleton { public: // 2、提供获取单例对象的接口函数 static Singleton GetInstance() { if (_psinst nullptr) { // 第一次调用GetInstance的时候创建单例对象 _psinst new Singleton; } return *_psinst; } // 一般单例不用释放。 // 特殊场景1、中途需要显示释放 2、程序结束时需要做一些特殊动作如持久化 static void DelInstance() { if (_psinst) { delete _psinst; _psinst nullptr; } } void Add(const pairstring, string kv) { _dict[kv.first] kv.second; } void Print() { for (auto e : _dict) { cout e.first : e.second endl; } cout endl; } class GC { public: ~GC() { lazy::Singleton::DelInstance(); } }; private: // 1、构造函数私有 Singleton() { // ... } ~Singleton() { cout ~Singleton() endl; // map数据写到文件中 FILE* fin fopen(map.txt, w); for (auto e : _dict) { fputs(e.first.c_str(), fin); fputs(:, fin); fputs(e.second.c_str(), fin); fputs(\n, fin); } } // 3、防拷贝 Singleton(const Singleton s) delete; Singleton operator(const Singleton s) delete; mapstring, string _dict; // ... static Singleton* _psinst; static GC _gc; }; Singleton* Singleton::_psinst nullptr; Singleton::GC Singleton::_gc;在第一次使用时才初始化单例实例而非程序启动时。这种方式避免了不必要的资源浪费但需要处理多线程环境下的线程安全问题