2016-02-13 64 views
0

我對使用C++的單例模式有個小問題。 比方說,我有下面的類:C++單例#define

namespace MyNameSpace 
{ 
    class Window_Singleton 
    { 
    private: 
     static Window_Singleton instance; 
     Window_Singleton(); 
     /* Some more private stuff here */ 

    public: 
     static Window_Singleton *GetInstance(); 
     ~Window_Singleton(); 
     /* Some more public stuff here */ 

    } 
} 

#define Window Window_Singleton.GetInstance() 

我有這個#define,使我並不總是有寫MyNameSpace::Window_Singleton.GetInstance().SomeMethod(),我現在可以使用更短的MyNameSpace::Window.SomeMethod()

但問題是:現在我不能在另一個命名空間中創建一個Window類,因爲我會遇到定義問題。

有沒有辦法提供#define沒有「打破」我的名字空間。某種「名稱空間本地」定義?

+1

的方式不使'#define' 「破發」 的命名空間是不是在這裏使用一個'#define'。你主要用它混淆你的代碼,只是不這樣做,你不會有問題 – user463035818

+0

但是,我沒有更短的方式來訪問我的單身人士 – danielspaniol

+0

如果你懶得打字你應該使用IDE而不是讓你的代碼難以讀取和發送命名空間 – user463035818

回答

2

由於宏是在編譯之前擴展的方式,預編譯器並不知道類,名稱空間等等。所以不行,如果你定義了一個宏Window它將在任何地方使用。

你可以做的是定義一個函數:

inline Window_Singleton& Window(){ 
    return Window_Singleton.GetInstance(); 
} 

,然後寫

Window().SomeMethod(); 

這基本上是一個額外的一對大括號,但它會保持你的代碼更清晰了很多。

1

我強烈建議您不要在這裏使用#define。它實際上不會垃圾郵件名稱空間,但它可以完成任何代碼,包括這個定義很難找到錯誤。例如,一旦符號Window定義,函數

Foo(Bar* Window){ /*...*/} 

被打破,在某些情況下,你將有一個艱難的時間來發現這樣的錯誤。此外,它使你的代碼更難閱讀。如果我要調用靜態函數來獲取一個實例,並調用一個方法,我希望的代碼看起來像這樣:

Window_Singleton::GetInstance().SomeMethod(); 

Window.SomeMethod(); 

看起來更像是調用一些全球性的方法實例。我的意思是你可以使用全球

Window_Singleton Window; 

但據我所知,你不想使用一個全局的單身人士。總之:如果它反映了你真正想要做的事情,你的代碼很容易閱讀。調用靜態方法在調用靜態方法時最不容易混淆。如果您懶得輸入,請使用一些帶有代碼補全的編輯器,但是請勿使用潛在危險的定義使您的代碼難以閱讀。 PS:我不得不提到,在我的評論中,我有點困惑。 #defines完全不知道名稱空間。在編譯器開始實際工作之前,將它們替換爲代碼。這就是爲什麼將#defines引起的編譯器錯誤與符號定義的地方聯繫起來可能很困難(如果不是不可能的話)。

1

有沒有辦法提供#define而不「打破」我的名字空間。 某種「名稱空間本地」定義?

簡短的回答:第


較長的答案:宏沒有範圍。這就是將它們與其他C++功能區別開來的優點或缺點。


完整回答:

  • 不要使用宏,如果你能避免它。
  • 如果您使用任何宏,請使用ALL_CAPS
  • 根本不要使用Singleton模式。
  • 輕鬆書寫不是代碼質量的相關因素。

上的最後一點提示:如果您擔心MyNameSpace::Window_Singleton.GetInstance().SomeMethod()太長時間閱讀,那麼我可以肯定與同情。但是,這仍然不是使用宏攻擊你的代碼的原因。您應該在本地範圍內使用using,以便參考並可能使用auto以提高可讀性。例如:

void f() 
{ 
    using MyNameSpace::Window_Singleton; 
    auto& window = Window_Singleton.GetInstance(); 

    window.SomeMethod(); 
} 
0

我認爲沒有辦法使用宏,它會忽略範圍規則。

你可能會考慮一個typedef:

namespace MyNameSpace 
{ 
    class Window_Singleton 
    { 
    // ... 
    }; 

    typedef Window_Singleton WS; 

// ... 
} 

現在您的代碼可以使用typedef定義同義詞/別名...

// WS is alias/synonym for Window_Singleton 
MyNameSpace::WS::SomeMethod(); // access to static method 

MyNameSpace::WS ws; // declare instance 
ws.SomeMethod2();  // access instance 

提示 - 我試圖限制命名空間名稱到3個字母。考慮

namespace ETB; // for Exhauzt Tool Box 

namespace EWS; // for Exhauzt Window Singleton