C++特殊類設計單例模式...

文章目錄

    • 請設計一個類,不能被拷貝
    • 請設計一個類,只能在堆上創建對象
    • 請設計一個類,只能在棧上創建對象
    • 請設計一個類,不能被繼承
    • 請設計一個類,只能創建一個對象(單例模式)
      • 單例模式:
        • 餓漢模式:
        • 懶漢模式:
      • 懶漢模式的線程安全問題
        • 工廠模式
        • 觀察者模式

請設計一個類,不能被拷貝

  • 拷貝只會放生在兩個場景中:拷貝構造函數以及賦值運算符重載,因此想要讓一個類禁止拷貝, 只需讓該類不能調用拷貝構造函數以及賦值運算符重載即可。

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;
};

請設計一個類,只能在堆上創建對象

實現方式:

  1. 將類的構造函數私有,拷貝構造聲明成私有。防止別人調用拷貝在棧上生成對象。
  2. 提供一個靜態的成員函數,在該靜態成員函數中完成堆對象的創建
class HeapOnly
{
public:static HeapOnly* CreateObject(){return new HeapOnly;}
private:HeapOnly() {}// C++98// 1.只聲明,不實現。因為實現可能會很麻煩,而你本身不需要// 2.聲明成私有HeapOnly(const HeapOnly&);// C++11    HeapOnly(const HeapOnly&) = delete;
};

請設計一個類,只能在棧上創建對象

  • 方法一:同上將構造函數私有化,然后設計靜態方法創建對象返回即可。
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;
};

請設計一個類,不能被繼承

C++98方式:

  • C++98中構造函數私有化,派生類中調不到基類的構造函數。則無法繼承
class NonInherit
{
public:static NonInherit GetInstance(){return NonInherit();}
private:NonInherit(){}
};

C++11方法:

  • final關鍵字,final修飾類,表示該類不能被繼承。
class NonInherit final
{
public:// ...
};

請設計一個類,只能創建一個對象(單例模式)

設計模式:

  • 設計模式(Design Pattern)是一套被反復使用、多數人知曉的、經過分類的、代碼設計經驗的 總結。為什么會產生設計模式這樣的東西呢?就像人類歷史發展會產生兵法。最開始部落之間打 仗時都是人拼人的對砍。后來春秋戰國時期,七國之間經常打仗,就發現打仗也是有套路的,后 來孫子就總結出了《孫子兵法》。孫子兵法也是類似。

  • 使用設計模式的目的:為了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性。 設計模 式使代碼編寫真正工程化;設計模式是軟件工程的基石脈絡,如同大廈的結構一樣。

單例模式:

  • 一個類只能創建一個對象,即單例模式,該模式可以保證系統中該類只有一個實例,并提供一個 訪問它的全局訪問點,該實例被所有程序模塊共享。比如在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然后服務進程中的其他對象再 通過這個單例對象獲取這些配置信息,這種方式簡化了在復雜環境下的配置管理。

單例模式有兩種實現模式:

餓漢模式:
  • 餓漢模式:就是說不管你將來用不用,程序啟動時就創建一個唯一的實例對象,提前(main函數啟動時)創建好實例對象
    • 優點:實現簡單
    • 缺點:1、可能會導致進程啟動慢、2、如果兩個單例有啟動先后順序,那么餓漢無法控制
class A
{
public:static A * GetInstance(){return &_inst;}void Add(const string & key, const string & value){_dict[key] = value;}void Print(){for (auto& kv : _dict){cout << kv.first << ":" << kv.second << endl;}cout << endl;}
private:// 構造函數私有A(){}A(const A & aa) = delete;A& operator=(const A& aa) = delete;map<string, string> _dict;int _n = 0;static A _inst;
};// 在程序入口之前就完成單例對象的初始化
A A::_inst;int main()
{// 無法創建//A aa1;//A aa2;// 可以進行調用A::GetInstance()->Add("sort", "排序");A::GetInstance()->Add("left", "左邊");A::GetInstance()->Add("right", "右邊");A::GetInstance()->Print();// 拷貝構造禁止使用// A copy(*A::GetInstance());// copy.Print();// A::GetInstance()->Add("left", "剩余");// copy.Print();// A::GetInstance()->Print();// 賦值也無法使用// *A::GetInstance() = *A::GetInstance();return 0;
}
  • 如果這個單例對象在多線程高并發環境下頻繁使用,性能要求較高,那么顯然使用餓漢模式來避 免資源競爭,提高響應速度更好。
懶漢模式:
  • 如果單例對象構造十分耗時或者占用很多資源,比如加載插件啊, 初始化網絡連接啊,讀取 文件啊等等,而有可能該對象程序運行時不會用到,那么也要在程序一開始就進行初始化, 就會導致程序啟動時非常的緩慢。 所以這種情況使用懶漢模式(延遲加載)更好。

    • 優點:第一次使用實例對象時,創建對象。進程啟動無負載。多個單例實例啟動順序自由控制。
    • 缺點:復雜
class B
{
public:static B* GetInstance(){if (_inst == nullptr){_inst = new B;}return _inst;}void Add(const string& key, const string& value){_dict[key] = value;}void Print(){for (auto& kv : _dict){cout << kv.first << ":" << kv.second << endl;}cout << endl;}static void DelInstance(){if (_inst){delete _inst;_inst = nullptr;}}private:B(){}~B(){// 持久化:要求把數據寫到文件cout << "數據寫到文件" << endl;}B(const B& aa) = delete;B& operator=(const B& aa) = delete;map<string, string> _dict;int _n = 0;static B* _inst;// 期望main函數結束后自動調用class gc{public:~gc(){DelInstance();}};static gc _gc;
};B* B::_inst = nullptr;// 期望main函數結束后自動調用
B::gc B::_gc;int main()
{B::GetInstance()->Add("sort", "排序");B::GetInstance()->Add("left", "左邊");B::GetInstance()->Add("right", "右邊");B::GetInstance()->Print();B::GetInstance()->Add("right", "xxx");B::GetInstance()->Print();// 顯示的調用釋放B::DelInstance();cout << "xxxxxxxxxxx" << endl;return 0;
}

懶漢模式的線程安全問題

  • 懶漢模式的線程安全問題已經在 Linux多線程【線程互斥】 中講解:
    • 大概實現如下:

在這里插入圖片描述

  • 局部的靜態對象,是在第一次調用時初始化
  • C++11之前,他不是,也就說, C++11之前的編譯器,那么這個代碼不安全的
  • C++11之后可以保證局部靜態對象的初始化是線程安全的,只初始化一次
class Singleton
{
public:// 提供獲取單例對象的接口函數static Singleton& GetInstance(){// 局部的靜態對象,是在第一次調用時初始化// C++11之前,他不是,也就說, C++11之前的編譯器,那么這個代碼不安全的// C++11之后可以保證局部靜態對象的初始化是線程安全的,只初始化一次static Singleton inst;return inst;}private:// 構造函數私有Singleton(){cout << "Singleton()" << endl;}// 防拷貝Singleton(const Singleton& s) = delete;Singleton& operator=(const Singleton& s) = delete;
};int main()
{Singleton::GetInstance();return 0;
}
工廠模式
  • 用于創建對象的一個接口,讓子類決定實例化哪個類
class Product {
public:virtual void show() = 0;
};class ConcreteProduct : public Product {
public:void show() override {std::cout << "ConcreteProduct Show" << std::endl;}
};class Factory {
public:virtual Product* createProduct() = 0;
};class ConcreteFactory : public Factory {
public:Product* createProduct() override {return new ConcreteProduct();}
};
觀察者模式
  • 定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一主題對象
#include <iostream>
#include <list>
#include <string>class Observer {
public:virtual void update(std::string message) = 0;
};class ConcreteObserver : public Observer {
public:void update(std::string message) override {std::cout << "Received message: " << message << std::endl;}
};class Subject {
private:std::list<Observer*> observers;std::string message;public:void attach(Observer* observer) {observers.push_back(observer);}void notify() {for (auto observer : observers) {observer->update(message);}}void setMessage(std::string msg) {message = msg;}
};int main() {Subject subject;Observer* observer = new ConcreteObserver();subject.attach(observer);subject.setMessage("Hello, World!");subject.notify();delete observer;return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/38010.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/38010.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/38010.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

代發考生戰報:6月25號 南寧 HCIP-Transmission傳輸 H31-341考試884分通過

代發考生戰報&#xff1a;6月25號 南寧 HCIP-Transmission傳輸 H31-341考試884分通過 &#xff0c;今天我和同事兩個人去考的&#xff0c;我考試遇到1個新題&#xff0c;他遇到兩個新題&#xff0c;客服提供的題庫很穩定&#xff0c;全覆蓋了&#xff0c;輕松通過&#xff0c;考…

【語言模型】Xinference的部署過程

一、引言 Xinference&#xff0c;也稱為Xorbits Inference&#xff0c;是一個性能強大且功能全面的分布式推理框架&#xff0c;專為各種模型的推理而設計。無論是研究者、開發者還是數據科學家&#xff0c;都可以通過Xinference輕松部署自己的模型或內置的前沿開源模型。Xinfe…

pikachu靶場 利用Rce上傳一句話木馬案例(工具:中國蟻劍)

目錄 一、準備靶場&#xff0c;進入RCE 二、測試寫入文件 三、使用中國蟻劍 一、準備靶場&#xff0c;進入RCE 我這里用的是pikachu 打開pikachu靶場&#xff0c;選擇 RCE > exec "ping" 測試是否存在 Rce 漏洞 因為我們猜測在這個 ping 功能是直接調用系統…

性能評測系列:云架構擴展演進橫向對比

原始測評報告 性能評測系列&#xff08;PT-010&#xff09;&#xff1a;Spring Boot RDS for MySQL&#xff0c;高并發insert 性能評測系列&#xff08;PT-012&#xff09;&#xff1a;Spring Boot(K8s多實例) RDS for MySQL&#xff0c;高并發insert 性能評測系列&#xff…

一元線性回歸-R語言

# # 安裝包 # install.packages(ggplot2) # library(ggplot2) Sys.setlocale(category LC_ALL, locale English_United States.1252) # Sys.setlocale("LC_ALL","Chinese") x <- c(18, 20, 22, 24, 26, 28, 30) y <- c(26.86, 28.35, 28.87,28.75,…

Linux——vim的配置文件+異常處理

vim的配置文件&#xff1a; [rootserver ~]# vim /etc/vimrc # 輸入以下內容 set nu # 永久設置行號 shell [rootserver ~]# vim /etc/vimrc 或者 vim ~/.vimrc set hlsearch "高亮度反白 set backspace2 "可隨時用退格鍵刪除 set autoindent…

期貨的杠桿怎么計算?

什么是杠桿系數 杠桿系數是指期貨合約價值與保證金之間的比例。它表示投資者只需投入少量資金&#xff0c;就可以控制價值更高的期貨合約。杠桿系數越高&#xff0c;投資者的資金放大倍數就越大&#xff0c;但風險也越大。 什么是期貨保證金呢&#xff1f; 期貨保證金&…

《HelloGitHub》第 99 期

興趣是最好的老師&#xff0c;HelloGitHub 讓你對編程感興趣&#xff01; 簡介 HelloGitHub 分享 GitHub 上有趣、入門級的開源項目。 github.com/521xueweihan/HelloGitHub 這里有實戰項目、入門教程、黑科技、開源書籍、大廠開源項目等&#xff0c;涵蓋多種編程語言 Python、…

Multicolor Dragon-MCD 六彩神龍_RSI

MCDX 六彩神龍 https://www.tradingview.com/script/u2dIgVpN-M2J-Indicator-MCDX/ MCDX is an indicator based on mutilple Relative Strength Index (RSI) with different period, then classify into 3 categories - Retailer, Hot Money and Banker - Green - Retailer零…

2024.06.28 刷題日記

394. 字符串解碼 給定一個經過編碼的字符串&#xff0c;返回它解碼后的字符串。 示例 1&#xff1a; 輸入&#xff1a;s “3[a]2[bc]” 輸出&#xff1a;“aaabcbc” 示例 2&#xff1a; 輸入&#xff1a;s “3[a2[c]]” 輸出&#xff1a;“accaccacc” 示例 3&#xff1a;…

怎么進行模型微調,以微調llama3為例

微調模型&#xff08;Fine-tuning&#xff09;通常涉及以下步驟&#xff0c;以微調 LLaMA 3 為例&#xff1a; 1. 準備工作 在開始微調之前&#xff0c;需要準備以下工作&#xff1a; 選擇預訓練模型&#xff1a;LLaMA 3 是一個大型的語言模型&#xff0c;可以通過 Hugging F…

react 中 Swiper vertical 模式下 autoHeight 失效的問題

Swiper 在 vertical 模式下 autoHeight 失效的問題&#xff0c;導致頁面出現多余的空白高度&#xff0c;網上找了很多方法都無效&#xff0c;我直接暴力更改。 <SwiperclassNameindex-swiperdirection{vertical}mousewheel{true}centeredSlides{true}autoHeight{true}slide…

VS2019+QT5.12.10: error MSB4036: 未找到“Join”任務。請檢查下列各項: 1.) 項目文件中的任務名

1、背景 兩個VS2019打開兩個相同的項目&#xff0c;一個里可以正常運行&#xff0c; 一個中一直報錯&#xff0c;&#xff0c;報的錯也是瞎幾把報的。。 2、重新安裝插件 之前在VS的擴展中在線安裝了qt插件&#xff0c; 安裝了一半&#xff0c;比較慢&#xff0c;直接強行退出…

傳媒行業指哪些?需要過等保嗎?

傳媒&#xff0c;一個人人都接觸的行業。相信大家都聽過傳媒&#xff0c;但具體傳媒行業是指什么&#xff0c;包括哪些&#xff0c;詳細很多人都不了解。這不一些人在問&#xff0c;傳媒行業指哪些&#xff1f;需要過等保嗎&#xff1f;這里跟我們小編一起來討論討論吧&#xf…

玩游戲就能學習亞馬遜云科技AWS技術并通過熱門技術認證考試??

亞馬遜AWS限時活動&#xff0c;玩免費游戲Cloud Quest Practitioner送AWS云從業證書考試25%折扣券(價值171元)&#xff0c;玩游戲的同時還能學知識一舉兩得。Cloud Quest是AWS出的一款3D角色扮演游戲/虛擬城市建造形式的實驗課程(游戲畫面有點像天際線)&#xff0c;大家通過完成…

【01-02】Mybatis的配置文件與基于XML的使用

1、引入日志 在這里我們引入SLF4J的日志門面&#xff0c;使用logback的具體日志實現&#xff1b;引入相關依賴&#xff1a; <!--日志的依賴--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version&g…

338. 比特位計數(leetcode)

338. 比特位計數&#xff08;leetcode&#xff09; 題目描述 給你一個整數 n &#xff0c;對于 0 < i < n 中的每個 i &#xff0c;計算其二進制表示中 1 的個數 &#xff0c;返回一個長度為 n 1 的數組 ans 作為答案。 示例1 輸入&#xff1a;n 2 輸出&#xff1a;[0…

Sorting

本節提供有關在數據網格中對數據進行排序的信息。 GridControl-Grid View Sort Data 默認情況下&#xff0c;最終用戶可以按任何列對數據進行排序&#xff0c;但使用MemoExEdit、ImageEdit和PictureEdit在位編輯器的列除外。在運行時&#xff0c;單擊列標題一次以升序排列數…

中國電信股份有限公司江西分公司招聘信息 7.5日截止

法律事務管理(南昌) 學歷要求 本科及以上學歷 崗位職責 1.依據國家法律、法規和相關規章規定,為公司其他部門提供日常法律服務與支持; 2.負責公司各類合同審核工作; 3.負責公司法律文件的起草和法律事務談判; 4.圍繞與公司業務有關的法律問題及法…

如何在Java中實現分布式緩存?

如何在Java中實現分布式緩存&#xff1f; 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們將深入探討在Java應用程序中如何實現分布式緩存&#xff0c;探…