【C++复习】C++特殊类总结

devtools/2024/9/24 18:26:10/

文章目录

  • 不能被拷贝
  • 只在堆上创建
  • 只能在栈上创建
  • 不能被继承
  • 饿汉单例 程序启动前就创建好
  • 懒汉单例 需要的时候即调用GetInstance时再创建单例

不能被拷贝

class CopyBan
{public:CopyBan(){}private:// C++98CopyBan(const CopyBan&);CopyBan& operator=(const CopyBan&);// C++11CopyBan(const CopyBan&) = delete;CopyBan& operator=(const CopyBan&) = delete;
};
  1. 私有:类外无法调用 类外无法定义
  2. 无定义:类内即使调用也无实现

只在堆上创建

析构函数私有化 + 提供销毁接口

class HeapOnly
{public:// 提供接口销毁堆上对象void Destroy(){delete this;}private:// 析构函数私有 导致无法在栈上创建对象~HeapOnly(){cout << "~HeapOnly()" << endl;}
};
int main()
{HeapOnly* hp = new HeapOnly;hp->Destroy();return 0;
}

构造函数私有 + 提供静态成员函数

class HeapOnly
{public:static HeapOnly* CreateObj(){return new HeapOnly;}private:HeapOnly(){}HeapOnly(const HeapOnly&) = delete;HeapOnly& operator=(const HeapOnly&) = delete;
};
int main()
{HeapOnly* hp = HeapOnly::CreateObj();return 0;
}

只能在栈上创建

class StackOnly
{public:static StackOnly CreateObj(){StackOnly obj;return obj;}private:StackOnly(){}
};
int main()
{StackOnly st1 = StackOnly::CreateObj();StackOnly* st2 = new StackOnly(st1);// error 这里仍然可以调用return 0;
}

不能通过禁用拷贝构造,CreateObj()返回栈上的对象是传值返回,需要拷贝构造函数。

在类里面写一个 operator new 并禁掉。使用 new时,默认调的是全局的 new,但是如果我们在类中写一个 operator new,那么当我们 new 一个该类的对象时,会优先调用我们自己写的 operator new,所以我们只需要把自己写的 operator new 禁掉即可。

new = operator new() + 构造函数

class StackOnly
{
public:static StackOnly CreateObj(){StackOnly obj;return obj;}// 实现类专属的 operator newvoid* operator new(size_t size) = delete;
private:StackOnly(){}
};

不能被继承

// C++98
class NonInherit
{public:static NonInherit GetInstance(){return NonInherit();}private:NonInherit(){}
};// C++11
class NonInherit final
{public:NonInherit(){}private:// ...
};

饿汉单例 程序启动前就创建好

程序启动前_inst静态对象就初始化完毕 之后使用该单例时调用GetInstancePtr()即可

class Singleton
{public://static Singleton& GetInstance()//{//    return inst;//}static Singleton* GetInstancePtr(){return &_inst;}private:static Singleton _inst;  // 声明Singleton(){}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;
};// 定义
Singleton Singleton::_inst;

指针版本

class Singleton
{
public:static Singleton* GetPtrAtOnly(){return _ponly;}private:static Singleton* _ponly;Singleton() {}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;
};
Singleton* Singleton::_ponly = new Singleton;int main()
{Singleton* instPtr = Singleton::GetPtrAtOnly();return 0;
}

懒汉单例 需要的时候即调用GetInstance时再创建单例

class Singleton
{
public:static Singleton* GetInstance(){// error 线程不安全//if (_inst == nullptr)//{//	_inst = new Singleton;//} ok but 效率低//_ptrmtx.lock();//if (_inst == nullptr)//{//	_inst = new Singleton;//}//_ptrmtx.unlock(); error 相当于没加锁//if (_inst == nullptr)//{//	_ptrmtx.lock();//	_inst = new Singleton;//	_ptrmtx.unlock();//}// okif (_inst == nullptr){_ptrmtx.lock();if (_inst == nullptr){_inst = new Singleton;}_ptrmtx.unlock();}return _inst;}
private:static Singleton* _inst;static mutex _ptrmtx;Singleton(){}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;
};
mutex Singleton::_ptrmtx;
Singleton* Singleton::_inst = nullptr;

C++11后支持这样写且线程安全

// 懒汉
class Singleton
{
public:static Singleton& GetInstance() {static Singleton instance; return instance;}private:Singleton() {}~Singleton() {}Singleton(const Singleton& s) = delete;Singleton& operator=(const Singleton& s) = delete;
};class Singleton2
{
public:static Singleton2* GetPtrAtOnly(){static Singleton2 one;return &one;}private:Singleton2() {}~Singleton2() {}Singleton2(const Singleton2& s) = delete;Singleton2& operator=(const Singleton2& s) = delete;
};int main() 
{Singleton& singletonInstance = Singleton::GetInstance();Singleton2* instPtr = Singleton2::GetPtrAtOnly();return 0;
}

http://www.ppmy.cn/devtools/116611.html

相关文章

广州电影产业博览交易会将于本周五开始

“影动广州绽放世界”广州电影产业博览交易会由广州市人民政府主办&#xff0c;广州市委宣传部承办&#xff0c;将在广交会展馆A区4.2及5.2馆启幕。本届广州影博会聚焦电影产业交易、科技创新和消费市场&#xff0c;链接国内外电影资源&#xff0c;活动内容丰富。设置电影主题展…

Linux——K8s集群部署过程

&#xff11;、环境准备 &#xff08;1&#xff09;配置好网络ip和主机名 control: node1: node2: 配置ip 主机名的过程省略 配置一个简单的基于hosts文件的名称解析 [rootnode1 ~]# vim /etc/hosts // 文件中新增以下三行 192.168.110.10 control 192.168.110.11 node1 1…

OLED(1)原理篇

文章目录 1 OLED 硬件1.1 SSD1306 简介1.2 SSD1306 框图及引脚定义1.3 4-Pin 模块原理图&#xff08;I2C&#xff09;1.4 7-Pin 模块原理图&#xff08;SPI&#xff09; 2 通信协议2.1 6800 并口协议2.2 8080 并口协议2.3 4-wire SPI2.4 3-wire SPI2.5 I2C 3 总结4 参考 1 OLED…

Android String资源文件中,空格、换行以及特殊字符如何表示

空格&#xff1a; 例&#xff1a;<string name"test">test test</string> 换行&#xff1a;\n 例&#xff1a;<string name"test">test \n test</string> tab&#xff1a;\t …

问:Java中final关键字有哪些用法和作用?

final 关键字在 Java 中确实是一个重要且常用的概念&#xff0c;理解它对掌握 Java 语言特性很有帮助。笔者基于这篇内容&#xff0c;说明 final 的作用与用法&#xff0c;并解释编译器对 final 域的重排序规则。 1. 被 final 修饰的类不可以被继承 public final class Final…

Python爬虫之requests(二)

Python爬虫之requests&#xff08;二&#xff09; 前面演示了requests模块的四种请求方式。接下来再来演示下综合的练习。 一、requests模块综合练习 需求&#xff1a;爬取搜狗知乎某一个词条对应的某个范围页码表示的页面数据。 点开搜狗首页&#xff0c;有一个知乎的版块…

Linux 信号的产生

1. 概念 在Linux系统中&#xff0c;信号是一种进程间通信的机制&#xff0c;它允许操作系统或其他进程向特定进程发送异步通知。我们可以通过命令 kill -l来查看信号的种类&#xff1a; Linux系统中的信号可以分为两大类&#xff1a;传统信号和实时信号。从上图可以看出它们分…

Redis 命令:

1.通用键命令 set key value&#xff1a;设置指定键的值。get key&#xff1a;获取指定键的值。del key [key ...]&#xff1a;删除一个或多个键。expire key seconds&#xff1a;设置键的过期时间&#xff08;以秒为单位&#xff09;。ttl key&#xff1a;查看键的剩余存活时间…