2014-03-06 84 views
4

有一個singleton Logger類,我覺得每次打印方法被調用時都會寫Logger::GetInstance()很醜。我能想到的唯一解決方案是#define。還有什麼更好的,或者在這種情況下這個宏是否合理?這個預處理器指令在這裏可以接受嗎?

#include <iostream> 
#include <fstream> 

class Logger 
{ 
public: 

    static Logger& GetInstance(); 
    ~Logger(); 
    template <typename T> 
    void Print(const T &t); 
    void SetNewline(bool b); 
    void SetLogging(bool b); 

private: 

    Logger(); 
    Logger(const Logger&); 
    void operator=(const Logger&); 

    bool newline; 
    bool log; 
    std::ofstream file; 
}; 

int main() 
{ 
    #define logger Logger::GetInstance() 
    logger.Print("Hello"); 
    //Logger::GetInstance().Print("Hello"); 
} 
+0

有每個需要登錄的對象,在構造函數中調用GetInstance()並存儲引用? –

+0

爲什麼''定義'main'方法中的記錄器? '#define'不尊重範圍。如果你只想讓'logger'在那裏,你也可以使用'Logger&logger = Logger :: GetInstance()'。 – anderas

+1

有點偏離主題,但我更願意將'Logger'作爲參數傳遞給任何需要記錄的函數。記錄器創建的單點將是主要功能。我不喜歡全球可用的可修改狀態。 – Onur

回答

3

兩種選擇歡呼和心連心。 - 阿爾夫的回答是:

你可以給記錄器的名稱,如果你需要它不止一次在一個範圍:

Logger& logger = Logger::GetInstance(); 

// ... 

logger.Print("Hello, world"); 

或者你可以使測井方法靜態還有:

static void Logger::Print(const T &t) { 
    Logger::GetInstance().Print(t); 
} 

然後靜態地稱他們爲:

Logger::Print("Hello world!"); 

你可以說在客戶端它不應該的問題如果實際上有一個實例 - 構造函數是私有的,所以它們無論如何都不能創建自己的實例。所以靜態方法是否創建一個實例應該不是他們關心的問題。在這種情況下,使用名爲GetInstance的公共方法實際上暴露了不相關的實現細節。

+0

靜態打印方法是目前爲止提出的最佳方法之一。 – Onur

+0

哇。儲存參考資料甚至沒有發生在我身上,我立即想到,好吧,在這裏不能有任務。這很清楚,謝謝。 – Innkeeper

+0

@Onur是的,當我想到這一點時,是否有任何情況,你有一個單身類,但你不能讓它的方法是靜態的? – Innkeeper

4

注,因爲你明顯地定義一個宏「本地」,即宏不尊重範圍

爲什麼不直接定義的,而不是一個宏觀的功能:

inline 
auto logger() -> Logger& { return Logger::GetInstance(); } 

,那麼你可以寫只是

logger().Print("Hello"); 
+1

+1,但爲什麼尾隨返回類型?我認爲這不適用於此目的。 – Angew

+0

我將它用作**單**和**統一**函數聲明語法。爲什麼使用多個語法? –

+0

'inline Logger&logger {...}對於C++之前的0x ... – anderas