簡體   English   中英

在C ++中,如何初始化在Singleton模板中聲明的私有類的靜態成員?

[英]In C++, how to initialize static member of a private class declared inside a Singleton template?

好吧,我應該簡單地說我想創建一個我可以繼承的基礎Singleton類,以及我希望通過模板實現的方式。

為了避免內存泄漏,我不直接使用指向實例的指針,而是使用將處理刪除指針的私有類。

這是我的實際代碼(不工作):

template <typename T> class Singleton
{
private:
    class PointerInstance
    {
    private:
        T* instance;
    public:
        PointerInstance() : instance(0) {}
        ~PointerInstance() { delete instance; } // no memory leak !
        T* Get()
        {
            if ( !instance ) {
                instance = new T();
            }
            return instance;
        }
    };
    static PointerInstance PInstance;
public:
    static T* pGetInstance(void)
    {
        return PInstance.pGet();
    };
protected:
    Singleton(void){};
    ~Singleton(void){};
};

這是典型的派生類聲明應該是這樣的:

class Child : public Singleton<Child>
{
    friend class Singleton<Child>;
    Child();
    // etc...
};

基本上缺少的是我作為Singleton的每個T類的PInstance實例。

我的問題是:有沒有辦法一勞永逸地在包含上面代碼的Singleton.h中使用一些通用代碼行,或者除了為每個代碼添加一些特定的代碼行之外別無選擇衍生類?

(Bonus:有沒有更好的方法在C ++中使用Singleton類?)

template <typename T> 
typename Singleton<T>::PointerInstance Singleton<T>::PInstance;

在類之外的標題中。 請注意,無論您在PInstance的默認構造函數中編寫什么,如果您從不調用pGetInstance或從未以非另一種方式從非模板代碼引用PInstance ,則永遠不會執行代碼。 但那應該沒問題。

這是一種編寫CRTP Singleton而沒有內存泄漏的簡單方法:

template <class T>
class Singleton
{
  friend class T;
private:
  Singleton() {};
  ~Singleton() {};
  Singleton(const Singleton&); // not implemented
  const Singleton& operator=(const Singleton&); // not implemented

public:
  static T* pGetInstance()
  {
    static T theInstance;
    return &theInstance;
  }
};

用法與問題中的相同。

也許你想看看已經有一個通用的SingletonHolder<>類的Loki

首先,我建議你盡可能避免使用單身人士。 他們被過度使用了。

如果你必須使用它們,我真的不會得到這種新的流行方式(必須出現在某個地方的日記中,因為我看到現在每個人都使用它)來自Singleton。 這樣做會導致解決的問題。

如果你必須有一個,那么初始化它的最好方法是使用boost :: once。 您需要在源代碼中執行類似的操作,其中Foo是您的類。

這3個都是在Foo和私有中靜態聲明的

Foo* Foo::instance = NULL;
boost::once_flag Foo::flag = BOOST_ONCE_INIT;
void Foo::init()
{
   Foo::instance = new Foo;
};

這也是靜態的,是獲取實例的公共方法

Foo & Foo::getInstance()
{
   boost::call_once(init, Foo::flag);
   return *Foo::instance;
}

Foo的構造函數不能拋出。

請注意,此技術可以更廣泛地用於線程安全的一次加載惰性評估情況,而不僅僅是單例。 boost :: once的新版本首先獲取標志(現在是結構:提防),然后采用boost :: function,因此您可以在信息中使用boost :: bind進行創建。

要刪除單例,可以在編譯單元級別創建boost :: shared_ptr並將指針綁定到它,並使用自定義刪除器作為類的靜態成員,以便刪除可以保持私有。 您的刪除器將能夠調用刪除,並且您的init函數將可以訪問刪除函數(也是私有的)以使用它初始化shared_ptr。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM