2011-11-21 63 views
0

This post就是我剛纔讀的。如何在C++中實現Singleton

他在C++中實現Singleton的方式讓我感到困惑。我得到了這幾個問題,而且這裏是他的代碼:

template<typename T> 
class Singleton { 
public: 
    static T& getInstance() { //Question 1 
     return instance; 
    } 
private: 
    static T instance; 
}; 

class DebugLog : public Singleton<DebugLog> { //Question 2 
public: 
    void doNothing() {} 
}; 

問題

  1. 我想我們應該把static T& getInstance()的定義類主體以外的,對不對?

  2. 他試圖讓class DebugLog成爲一個單獨的類,但是當他繼承Singleton<DebugLog>時,DebugLog不存在了吧?如果對,那麼模板類Singleton如何實例化一個不存在的類?

+4

1 - 你不需要。 2 - [好奇地重複出現的模板模式](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)。 – birryree

+0

@birryree,謝謝。 – Alcott

回答

1
  1. 這肯定會是更清潔,如果函數是的 定義在類外,使代碼更容易閱讀和維護。然而,在這個 的情況下,完整的課程足夠小,以至於 的差別不是很大,當然,因爲我們正在處理模板,所以在每個翻譯單元中仍然必須包含實際定義 它使用它。

C++標準不存在「的」與問候類(或任何其他 )說。在模板實例化處,名稱查找找到 DebugLog,並發現它是一個類(因此是一個類型)。在那一點上, 它是一個不完整的類型,只有有限的東西,你可以做一個不完整的類型 。如果實例化的類模板 沒有做任何需要完整類型的事情(並且Singleton 沒有),那麼沒有問題。 (請注意,此時只有類 定義被實例化;類成員函數 在使用前不會被實例化。)

我可能會補充說,您發佈的 代碼中仍缺少一件重要的東西:聲明 Singleton::instance沒有定義。您仍然需要添加:

template<typename T> T Singleton<T>::instance; 

某處。

+0

是的,這是缺少的。此外,爲了使Singleton成爲一個真正的Singleton,我認爲我們應該讓Singleton的Singleton ()成爲一個protected/private成員函數,對吧? – Alcott

+0

@Alcott由於'Singleton '被設計爲派生自,因此使其構造器受到保護似乎是一個好的舉措。有一件事'Singleton '不能做,那需要做的是確保'DebugLog'具有一個私有構造函數,並且'Singleton '是朋友,爲了使用它。 –

+0

沒錯,:)。另一件事是,成員函數何時會在模板類中實例化? – Alcott

5

1)不,不管你如何構造你的代碼。 Singleton是不是一個類,順便說一句:這是一個模板。由於無論如何,完整的模板定義必須在任何實例化站點都可訪問,因此您可以定義所有內聯。

2)class DebugLog : public Singleton<DebugLog>很好。我們不是從一個不存在的階級繼承而來的;相反,我們從類Singleton<DebugLog>繼承。模板可以在不完整的類型上實例化。 (有幾個規則,你可以做什麼,不能做這樣的類型參數。)

例如,template <typename T> class Foo { };肯定可以在沒有問題的任何類型上實例化。更有趣的是,template <typename T> struct PointerFactory { typedef T * type; };可以在任何類型上實例化,完成與否。在目前情況下,CRTP中模板參數的目的僅僅是爲了通知基類它的最終派生類型,所以這是完全正確的。

+0

這是否意味着,當一個類繼承模板類時,模板參數是什麼並不重要,對吧? – Alcott

+0

@Alcott:這與繼承沒有任何關係。唯一的問題是你是否可以實例化模板。 –

-3

您必須在此情況下,使用指針T:

template<typename T> 
class Singleton { 
public: 
    static T& getInstance() { 
     static T * instance = NULL; 
     if (!instance) 
      instance = new T; 
     return *instance; 
    } 
}; 

class DebugLog : public Singleton<DebugLog> { //Question 2 
    public: 
     void doNothing() {} 
}; 
+0

你爲什麼「必須」使用指針? – duedl0r

+0

-1您不僅「不得」使用靜態指針實例,還不會破壞代碼中的對象。 – Artyom