首頁 > 軟體

C++使用宏函數實現單例模板詳解

2023-02-12 06:01:14

在我們日常開發中,無可避免需要使用單例模式進行設計類物件,那麼實際上我們寫單例格式基本都是一樣的,那麼每次都要寫幾乎一模一樣的程式碼來實現我們需要的單例物件是不是會覺得很累?下面博主提供一種單例模板來完成我們日常設計單例類,提高工作效率。既然封裝了,那麼當然是封裝一個執行緒安全的單例模板,如下:

ISingleton.hpp

#pragma once
#include <stdlib.h>
#include <assert.h>
#include <thread>
#include <mutex>


/******************************************************************************/
/**********************ufgnix0802:單例宏定義(執行緒安全)*************************/
/******************************************************************************/

#define SINGLETON_CLASS_DEFAULT(Class)                                          
    private:                                                                    
        Class() {}                                                              
        ~Class() {}                                                             
        Class(Class &other) {}                                                  
        Class(const Class &other) {}                                            
        Class& operator=(Class &other) {}                                       
        Class& operator=(const Class &other) {}                                 


#define SINGLETON_CLASS_FUNC_DECL(Class)                                        
    public:                                                                     
        static Class& Ins();                                                    
    private:                                                                    
        static void InitSingleton();                                            
                                                                                
        static void Release();                                                  
                                                                                
        SINGLETON_CLASS_DEFAULT(Class)                                          
private:                                                                        
    static std::once_flag m_singletonFlag;                                      
    static Class* m_ins;

/* https://liam.page/2020/10/27/implement-a-singleton-class-template-in-cxx/ */                         
/* https://liam.page/2017/01/17/layers-and-operation-system/#CPU-%E5%8A%A8%E6%80%81%E8%B0%83%E5%BA%A6 */

#define SINGLETON_CLASS_FUNC_IMPL(Class)                                        
    Class& Class::Ins() {                                                       
        /* 使用雙重檢查,外層檢查是為了避免鎖住過大的面積,從而導致鎖的競爭特別頻繁;*/
        /* 內層檢查是為了確保只在其它執行緒沒有搶佔鎖完成初始化工作而設計。*/           
        /* 這種做法在Java下是正確的,但是在C++下則沒有保證。*/                      
        /* std::once_flag 和 std::call_once:它們內部利用互斥量和條件變數組合,*/   
        /* 實現這樣的語意。值得一提的是,如果執行過程中丟擲異常,標準庫的設施不認為 */ 
        /* 這是一次「成功的執行」。於是其他執行緒可以繼續搶佔鎖來執行函數。 */          
        /* std:call_once確保函數或程式碼片段在多執行緒環境下,只需要執行一次。 */        
        std::call_once(m_singletonFlag, &Class::InitSingleton);                 
        assert(m_ins != NULL);                                                  
        return *m_ins;                                                          
    }                                                                           
                                                                                
    void Class::InitSingleton() {                                               
        m_ins = new Class;                                                      
        if (m_ins) {                                                            
        /* C 庫函數 int atexit(void (*func)(void)) 當程式正常終止時,呼叫指定的*/  
        /* 函數func。您可以在任何地方註冊你的終止函數,*/                           
        /* 但它會在程式終止的時候被呼叫。*/                                        
                ::atexit(Release);                                              
        }                                                                       
    }                                                                           
                                                                                
    void Class::Release() {                                                     
         if (m_ins) {                                                           
              delete m_ins;                                                     
              m_ins = NULL;                                                     
         }                                                                      
    }                                                                   


#define SINGLETON_CLASS_VARIABLE_IMPL(Class)                                    
        std::once_flag Class::m_singletonFlag;                                  
        Class* Class::m_ins = NULL;


#define SINGLETON_CLASS_IMPL(Class)                                             
        SINGLETON_CLASS_VARIABLE_IMPL(Class)                                    
        SINGLETON_CLASS_FUNC_IMPL(Class)                                        

使用方式

注意,如果我們的單例類物件在.hpp檔案中那麼可能出現重定義的問題,博主設計的單例模板,只適用於.h和.cpp,即宣告和定義分開單例類物件。

Aclass.h

#include "ISingleton.hpp"


class Aclass {
    //宣告
    SINGLETON_CLASS_FUNC_DECL(Aclass)

public:
    int a;
    
};

Aclass.cpp

#include "Aclass.h"

//定義
SINGLETON_CLASS_IMPL(Aclass);

main.c

#include "Aclass.h"
int main() {
    //Aclass a;  err
    Aclass::Ins().a = 5;
    std::cout << Aclass::Ins().a << std::endl;
    return 0;
}

執行結果:

到此這篇關於C++使用宏函數實現單例模板詳解的文章就介紹到這了,更多相關C++宏函數實現單例模板內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com