2011-07-22 13 views
3

我正在爲C++構建基於樹的調試/日誌記錄系統。在全局函數中獲取對象地址或NULL的統一方法

它的「用戶界面」是一個宏,它將用戶定義的消息和呼叫站點信息(文件,行,對象地址)傳遞給特殊功能,然後執行日誌記錄。

該函數使用對象地址按對象實例對消息進行分組。

目前,它看起來像這樣:

// in logging system header 
#define msg (event_level, message) \ 
    do_logging_ (event_level, __FILE__, __LINE__, this, message) 

... 

// in code 
msg (MSG_WARNING, "some text"); 

我想問一下,有沒有一些統一的方式(在msg宏可用),以獲得NULL,而不是this其中沒有定義this(全局/靜態函數)?

+0

理論上(就編譯器可以說),這些代碼也可能出現在函數之外;當在全局變量的初始化器中使用表達式時,表達式可以出現在全局作用域中,甚至可以在靜態常量類成員的類中使用。 – MSalters

回答

4

你可以改變你的宏定義:

#define msg (event_level, message, THIS) \ 
    do_logging_ (event_level, __FILE__, __LINE__, THIS, message) 

用法:

msg (MSG_WARNING, "some text", this); // in member methods 
msg (MSG_WARNING, "some text", NULL); // otherwise 
+0

或者,通過爲三參數版本提供'this'或'NULL'的兩個選項提供兩個包裝器宏,減少調用者站點上的冗餘。儘管你可以自由發揮一些自由,因爲你不能從外部發出給定對象的消息(例如'friend'函數) - 但沒有人說三參數版本必須變成私有的。 – delnan

+0

@delnan,我也在想你的建議解決方案;但超過一個只是保持簡單。所以發佈。 – iammilind

+0

似乎這是唯一的方法...不是那麼'優雅'的解決方案,但無論如何謝謝。 – intelfx

1

我覺得這也不是沒有可能修改你的類要登錄的代碼。如果你願意這樣做,但是,你能得到你想要從模板像這樣的日誌記錄功能的所有類:

template <typename T> 
    class loggable_class 
    { 
    protected: 
     T* get_this() { return static_cast <T*> (this); } 
    }; 

例如:

class A : public loggable_class<A> 
    { 
     ... 
    }; 

的另外一個全局定義功能get_this()將在非成員函數被使用:

inline void* get_this() 
    { 
     return NULL; 
    } 

測井宏將如下所示:

#define msg (event_level, message) \ 
     do_logging_ (event_level, __FILE__, __LINE__, get_this(), message) 
+0

公平起見,您寧願在成員函數中使用'dynamic_cast '。儘管如此,您可能會將混淆鑽石繼承的問題。 –

+0

我剛剛嘗試過,但在靜態成員函數中使用時,編譯器顯然更喜歡'loggable_class :: get_this()'通過全局'get_this()'。並且由於沒有對象的呼叫而失敗。 – intelfx

+0

動態轉換爲void *意味着您錯過了動態轉換的一部分功能。如果沒有vtable,你不能在功能上dynamic_cast。 – dascandy