2010-02-23 101 views
12

我有一些C++代碼,其中包括一種稱爲CreateDirectory().的方法此前代碼僅使用STL和Boost,但最近我不得不包含<windows.h>,因此我可以查找CSIDL_LOCAL_APPDATA如何避免與Windows頭文件中定義的宏發生名稱衝突?

現在,這個代碼:

filesystem.CreateDirectory(p->Pathname()); // Actually create it... 

不再編譯:

error C2039: 'CreateDirectoryA' : is not a member of ... 

相當於本宏winbase.h

#ifdef UNICODE 
#define CreateDirectory CreateDirectoryW 
#else 
#define CreateDirectory CreateDirectoryA 
#endif // !UNICODE 

預處理器重新定義了我的方法呼叫。有沒有任何可能的方法來避免這種命名衝突?或者我必須重新命名我的CreateDirectory()方法?

+6

現在你知道爲什麼Bjarne Stroustrup想要擺脫C預處理器 - 參見'C++的設計和演變'。 – 2010-02-23 21:09:22

+0

可能與答案重複:http://stackoverflow.com/questions/1394910/how-to-tame-the-windows-headers-useful-defines – 2010-02-23 21:24:43

+0

請投票:http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/6656174-have-a-version-of-windows -h-that-t-define-ma – 2014-11-04 14:10:20

回答

12

如果你只是重命名你的CreateDirectory方法,你會更好。如果你需要使用Windows API,與Windows.h戰鬥是一場失敗的戰鬥。

可以肯定的是,如果你是一致的在包含windows.h,這仍然是編譯。 (雖然你可能在其他地方有問題)。

+0

+1始終包含windows.h,如果可以,+1沒有與它作鬥爭並重命名以避免......我有'InitiateShutdown()'這個問題,並且所有嘗試解決方法只是導致了新問題。 – 2010-02-23 22:13:10

+1

有時候很難找到除MS以外的更好的名字。 – user1633272 2017-09-21 03:59:44

9

和#undef CreateDirectory

7

您可以創建一個模塊#include <windows.h>,其唯一目的是和查找CSIDL_LOCAL_APPDATA包裹在一個函數。

int get_CSIDL_LOCAL_APPDATA(void) 
{ 
    return CSIDL_LOCAL_APPDATA; 
} 

順便說一句,做好了解出現的事情!

+0

聰明的解決方案。 – 2010-02-23 21:29:54

-2
#pragma push_macro("CreateDirectory") 

如果什麼都行不通,而不是重命名,你可以使用你自己的命名空間作爲你的函數。

+2

命名空間不會解決此問題。預處理器將其CreateDirectory方法重命名爲其他內容。 – 2010-02-23 22:25:32

+0

你說得對,我弄錯了。我的解決方案只是一些可選的重命名方法。 – AureliusMarcus 2010-02-23 22:27:55

1

作爲開發跨平臺代碼庫的開發人員,這是一個問題。處理它的唯一方法是

  • 確保windows.h是 - 在Windows上至少構建 - 通用包含。然後,CreateDirectory宏將在每個編譯單元中定義,並且通常被CreateDirectoryW替代。預編譯的頭非常適合這種

,或者,如果這是一個不愉快的命題,(這是對我來說)

  • 分離WINDOWS.H使用到Windows特定的實用程序文件。創建導出基本所需功能的文件。頭文件必須使用兼容的數據類型,但不要依賴於包含windows.h。 cpp實現文件必須(顯然)使用windows.h。

如果您utlility功能需要包括與衝突的符號項目的頭文件,然後下面的模式是必要的:

#include <windows.h> 
#ifdef CreateDirectory 
#undef CreateDirectory 
#endif 
// etc 
#include "some_class_with_CreateDirectory_method.h" 
// ... 

您將需要再明確地調用任何Windows API函數非宏版本你有#undef'd - CreateDirectoryA或W等

0

push宏,undefpop再宏:

#pragma push_macro("CreateDirectory") 
#undef CreateDirectory 
void MyClass::CreateDirectory() 
{ 
// ... 
} 
#pragma pop_macro("CreateDirectory") 
0

請注意,名稱衝突通常來自包含某個頭文件。在那之前,像CreateDirectory和GetMessage這樣的東西不會被拉進可視化和代碼編譯而沒有問題。

您可以將這樣一個包含分離到一個包裝頭文件中,並在其末尾包含「#undef whatever」。然後,無論你有什麼名字相撞,都會消失。當然,除非你需要在你自己的代碼中使用這些宏(是的,所以很可能是 ...)