C++特殊类设计与类型转换详细代码示例 常见的特殊类的设计1.请设计一个类不能被拷贝拷贝只会发生在两个场景中拷贝构造函数以及赋值运算符重载因此想要让一个类禁止拷贝只需要让该类不能调用拷贝构造函数以及赋值运算符重载即可。C98写法将拷贝构造函数与赋值运算符重载只声明不定义并且将其访问权限设置为私有即可。12345678classCopyBan{//...private:CopyBan(constCopyBan c);CopyBan operator(constCopyBan c);//...};原因1.设置成私有如果只声明没有设置成private用户自己如果在类外定义了就不能禁止拷贝了。2.只声明不定义不定义是因为该函数根本不会调用定义了其实也没有什么意义不写反而还简单而且如果定义了就不会防止成员函数内部拷贝了。C11写法C11扩展delete的用法delete除了释放new申请的资源外如果在默认成员函数后面跟上delete表示让编译器删除掉该默认成员函数。1234567classCopyBan{//...CopyBan(constCopyBan c)delete;CopyBan operator(constCopyBan c)delete;//...};2.请设计一个类只能在堆上创建对象实现方式1.将类的构造函数设置为私有拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。2.提供一个静态的成员函数在该静态成员函数中完成堆对象的创建。12345678910111213141516171819classHeapOnly{public:staticHeapOnly* CreateHeapObj(){returnnewHeapOnly;}private:HeapOnly(){ }//C98方式//1.只声明不实现。因为实现可能会很麻烦而你本身并不需要//2.声明成私有HeapOnly operator(constHeapOnly);//C11方式HeapOnly operator(constHeapOnly) delete;};3.请设计一个类只能在栈上创建对象方法同上述将构造函数私有化然后设计静态方法创建对象返回即可。123456789101112131415161718192021classStackOnly{public:staticStackOnly CreateStackObj(){returnStackOnly();}//禁掉operator new可以把下面用new 调用拷贝构造申请对象给禁掉//StackOnly obj StackOnly::CreateStackObj();//StackOnly* ptr new StackOnly(obj);void* operatornew(size_tsize) delete;voidoperatordelete(void* p) delete;private:StackOnly():_a(0){ }int_a;};4. 请设计一个类不能被继承C98方式把类的构造函数私有化派生类调不到基类的构造函数就无法继承。123456789101112C98中构造函数私有化派生类中调不到基类的构造函数则无法继承classNonInherit{public:staticNonInherit GetInstance(){returnNonInherit();}private:NonInherit(){ }};C11方法final关键字final修饰类表示该类不能被继承。ps(final还能修饰虚函数表示该虚函数不能被重写。)12345final 关键字final修饰类表示该类不能被继承。classA final{//..};5.请设计一个类只能创建一个对象单例模式设计模式设计模式Design Pattern是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。为什么会产生设计模式这样的东西呢就像人类历史发展会产生兵法。最开始部落之间打仗时都是人拼人的对砍。后来春秋战国时期七国之间经常打仗就发现打仗也是有套路的后来孙子就总结出了《孙子兵法》。孙子兵法也是类似。使用设计模式的目的为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。设计模式使代码编写真正工程化设计模式是软件工程的基石脉络如同大厦的结构一样。单例模式一个类只能创建一个对象即单例模式。该模式可以保证系统中该类只有一个实例并提供一个访问它的全局访问点该实例被所有程序模块共享。比如在某个服务器程序中该服务器的配置信息存放在一个文件中这些配置数据由一个单例对象统一读取然后服务进程中的其他对象再通过这个单例对象获取这些配置信息这种方式简化了在复杂环境下的配置管理。单例模式有两种实现模式1.饿汉模式一开始main函数之前就创建单例对象就是说不管你将来用还是不用程序启动时就会创建一个唯一的实例对象。12345678910111213141516171819202122232425262728饿汉模式优点简单缺点可能会导致进程启动慢且如果有多个单例类对象实例启动顺序不确定。classSingleton{public:staticSingleton* GetInstance(){returnm_instance;}private://构造函数私有化Singleton(){}//C98防止拷贝Singleton(constSingleton);Singleton operator(constSingleton);//or//C11Singleton(constSingleton) delete;Singleton operator(constSingleton) delete;staticSingleton m_instance;};Singleton Singleton::m_instance;//在程序入口之前就完成单例对象的初始化但是如果这个单例对象再多线程高并发环境下频繁使用性能要求比较高那么显然使用饿汉模式来避免资源竞争提高响应速度更好。2.懒汉模式如果单例对象构造十分耗时或者占用很多资源比如加载插件啦初始化网络连接啦读取文件啦等等而有可能该对象程序运行时不会用到那么也要在程序一开始就进行初始化就会导致程序启动时非常的缓慢。所以这种情况就使用懒汉模式延迟加载更好。懒汉模式也会有线程安全问题在第一次初始化的时候要加锁。12345678910111213141516171819202122232425262728293031323334353637383940414243444546classSingleton{public:staticSingleton* GetInstance(){注意这里一定要使用Double-Check的方式加锁才能保证效率和线程安全if(nullptr m_pInstance){m_mtx.lock();//or--- unique_lockmutex lock(m_mtx);if(nullptr m_pInstance){m_pInstance newSingleton();}m_mtx.unlock();}}//实现一个内嵌的垃圾回收类classCGarbo{public:~CGarbo(){if(Singleton::m_pInstance)deleteSingleton::m_pInstance;}};//定义一个静态成员变量程序结束时系统自动调用它的析构函数从而释放单例对象staticCGarbo Garbo;main函数结束调用它的析构从而释放单例对象private://构造函数私有化Singleton(){}//防止拷贝Singleton(constSingleton) delete;Singleton operator(constSingleton) delete;staticSingleton* m_pInstance;//单例对象指针staticstd::mutex m_mtx;//互斥锁};Singleton* Singleton::m_pInstance nullptr;Singleton::CGarbo Garbo;std::mutex Singleton::m_mtx;C11中创建单例懒汉模式最简单的方法123456789101112131415161718classSingleton{public:局部的静态对象是在第一次调用时初始化staticSingleton GetInstance(){staticSingleton inst;returninst;}private:Singleton(){std::cout Singleton std::endl;}Singleton(constSingleton) delete;Singleton operator(constSingleton) delete;};C11之前这个代码是不安全的编译器不支持。C11之后可以保证局部静态对象的初始化是线程安全的只初始化一次。C11之后这个操作变成原子的了。C中的类型转换1.C语言中的类型转换在C语言中如果赋值运算符左右两侧类型不同或者形参与实参类型不匹配或者返回值类型与接收返回值类型不一致时就需要发生类型转换C语言中总共有两种形式的类型转换隐式类型转换和显式类型转换。1.隐式类型转换编译器在编译阶段自动进行能转就转不能转就编译失败。2.显式类型转换需要用户自己处理。123456789101112voidTest(){inti 1;//隐式类型转换doubled i;printf(%d,%.2lf\n, i, d);int* p i;//显式类型转换intaddress (int)p;printf(%x,%d\n, p, address);}缺陷转换的可视性比较差所有的转换形式都是以一种相同形式书写难以跟踪错误的转换。2.为什么C需要四种类型转换C风格的转换形式很简单但是有不少缺点1.隐式类型转换有些情况下可能会出问题比如说数据精度的丢失。2.显式类型转换将所有情况混合在一起代码不够清晰。因此C提出了自己的类型转换的风格注意C要兼容C语言所以在C中还是可以使用C语言那一套的类型转换。3.C强制类型转换标准C为了加强类型转换的可视性引入了四种命名的强制类型转换操作符static_cast , reinterpret_cast , const_cast , dynamic_cast3.1 stacit_caststatic_cast用于非多态类型的转换静态转换编译器隐式执行的任何类型转换都可用static_cast但它不能用于两个不相关的类型进行转换。用于两个相关类型/相近类型之间C里的隐式类型转换都可用这个static_cast强转。1234567intmain(){doubled 12.34;inta static_castint(d);std::cout a std::endl;return0;}3.2 reinterpret_castreinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释用于将一种类型转换为另一种不同的类型。可用于两个不相关类型之间进行强转。