2016-11-21 79 views
-2

在我的程序(wxWidgets,code :: blocks)中,我注意到一些我不太明白的行爲。如果我寫我的頭是這樣的:爲什麼#include語句的順序如此重要?

#ifndef RECORDTHREAD_H 
#define RECORDTHREAD_H 

#include <wx/thread.h> 
#include <wx/dialog.h> 
#include <wx/string.h> 

#include "Serial.h" 

class RecordTrackDialog; 

class RecordThread : public wxThread 
{ 
    public: 
     RecordThread(RecordTrackDialog* parent); 
     virtual ~RecordThread(); 
    protected: 
    private: 
     virtual ExitCode Entry(); 

     Serial m_serial; 
}; 

#endif // RECORDTHREAD_H 

(與#include "Serial.h"去年包括語句)當我改變了包括類的語句這一切工作正常,但:

#ifndef RECORDTHREAD_H 
#define RECORDTHREAD_H 

#include "Serial.h" 

#include <wx/thread.h> 
#include <wx/dialog.h> 
#include <wx/string.h> 

我得到的錯誤是這樣的:

||=== Build: Debug in WindowsDgpsGUI (compiler: GNU GCC Compiler) ===| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h||In function 'HWND__* CreateDialog(HINSTANCE, LPCTSTR, HWND, DLGPROC)':| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h|38|error: cannot convert 'LPCTSTR {aka const char*}' to 'LPCWSTR {aka const wchar_t*}' for argument '2' to 'HWND__* CreateDialogParamW(HINSTANCE, LPCWSTR, HWND, DLGPROC, LPARAM)'| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h||In function 'HFONT__* CreateFont(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCTSTR)':| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h|69|error: cannot convert 'LPCTSTR {aka const char*}' to 'LPCWSTR {aka const wchar_t*}' for argument '14' to 'HFONT__* CreateFontW(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCWSTR)'| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h||In function 'HWND__* CreateWindow(LPCTSTR, LPCTSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID)':| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h|94|error: cannot convert 'LPCTSTR {aka const char*}' to 'LPCWSTR {aka const wchar_t*}' for argument '2' to 'HWND__* CreateWindowExW(DWORD, LPCWSTR, LPCWSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID)'| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h||In function 'HMENU__* LoadMenu(HINSTANCE, LPCTSTR)':| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h|111|error: cannot convert 'LPCTSTR {aka const char*}' to 'LPCWSTR {aka const wchar_t*}' for argument '2' to 'HMENU__* LoadMenuW(HINSTANCE, LPCWSTR)'| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h||In function 'HWND__* FindText(LPFINDREPLACE)':| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h|126|error: cannot convert 'LPFINDREPLACE {aka FINDREPLACEA*}' to 'LPFINDREPLACEW {aka FINDREPLACEW*}' for argument '1' to 'HWND__* FindTextW(LPFINDREPLACEW)'| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h||In function 'HICON__* LoadIcon(HINSTANCE, LPCTSTR)':| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h|311|error: cannot convert 'LPCTSTR {aka const char*}' to 'LPCWSTR {aka const wchar_t*}' for argument '2' to 'HICON__* LoadIconW(HINSTANCE, LPCWSTR)'| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h||In function 'HBITMAP__* LoadBitmap(HINSTANCE, LPCTSTR)':| 
C:\wxWidgets-3.0.2\include\wx\msw\winundef.h|324|error: cannot convert 'LPCTSTR {aka const char*}' to 'LPCWSTR {aka const wchar_t*}' for argument '2' to 'HBITMAP__* LoadBitmapW(HINSTANCE, LPCWSTR)'| 
||=== Build failed: 7 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===| 

我不太明白這種行爲,因爲頭是一個線程,錯誤來自於使用這個線程的對話框。任何人都可以解釋爲什麼C++(或wxWidgets)的行爲是這樣的?

編輯:Serial.h

的包括

#ifndef SERIAL_H 
#define SERIAL_H 

#include <windows.h> 
//#include <wx/msw/winundef.h> 
#include <stdio.h> // necessary for sprintf 
#include <string> 

這似乎符合Marco的評論,但我不能包括一部分...

+6

什麼是'Serial.h'?正如你使用雙引號,它應該表示它是你的項目中的一個文件 - 如果你自己的頭文件依賴於其他頭文件,那麼你寫錯了'Serial.h'。 Serial.h'應該負責自己的包含。 – Dai

+2

可能相關:https://wiki.wxwidgets.org/WxMSW_Issues#The_windows.h_Header_File.2C_Macros_and_Compiling_Errors –

+0

向我們展示Serial.h。 –

回答

1

的問題是,<windows.h>取決於UNICODE標準(Windows下,這是)宏是否定義或不定義了不同的符號。如果您首先包含wxWidgets標頭,默認情況下采用Unicode構建,則在包含<windows.h>之前,它們會爲您定義UNICODE,並且一切都很好。

如果包括<windows.h>,再UNICODE不會在這個時候定義的,但是當你有wxWidgets的頭後,他們使用wxUSE_UNICODE=1(這是再次默認值),從而導致你觀察編譯問題。

確保您永遠不會遇到這種問題的最簡單方法是在項目設置或makefile中全局定義UNICODE

1

正如評論人士指出,這可能因爲Serial.h依賴於包含主文件(RecordThread.h?)的3 wx\xxxx文件中的定義。

將它們添加到Serial.h就像這樣,您將擁有與之前相同的效果。

#ifndef SERIAL_H 
#define SERIAL_H 

#include <wx/thread.h> 
#include <wx/dialog.h> 
#include <wx/string.h> 

#include <windows.h> 
//#include <wx/msw/winundef.h> 
#include <stdio.h> // necessary for sprintf 
#include <string> 

如果你打算做正確,你應該找出哪一個(或1),你實際上需要在Serial.h但加入所有的人都應該清除錯誤。

當編譯預處理器句柄#include時,好像指定的文件被複制到#include位置的主文件中一樣。這是一個遞歸的過程,文件可以是#include文件,#include文件等。

似乎有很多關於#include和一般初學者的預處理器的神祕主義。這實際上只是一個文本操作工具。

在現代C中的許多地方,您必須在使用它之前聲明(引入/定義)符號/標識符。如果在頭文件中聲明瞭該符號/標識符,則在使用該文件之前,應該使用該文件#include

0

只是一些常見的做法,跟進,這可能不是回答你的問題,但您指出正確的方向:

  • 永遠讓你做你在同一個文件中沒有#include同一頭文件,它意味着混亂但瞭解它使用如下圖:

有效期:

-#include "some.h" 
-#include "some1.h" 

有效:

-#include "some.h" 
--#include "some1.h" 

無效:

-#include "some.h" 
-#include "some1.h" 
--#include "some.h" 

所以不能嵌套,除非你知道你在做什麼..

一個可能的解決方案,您的問題將包括wx\thread.hwx\dialog.hwx\string.hSerial.h之內,試試吧,讓我知道吧

爲什麼打電話#include重要?

因爲只有你明白這樣的事情,阿里需要清理修理他的車,阿里不知道如何修理他的車,所以阿里會叫修理工修理它,所以在這裏我們可以說, (阿里取決於機械)

- #include "mechanic.h" 

- #include "Ali.h" 
+0

我明白你的意思,但是從這些類的每一箇中,將這些頭文件包含在'Serial.h'中是沒有多大意義的,因爲串口只是打開並從串口通信中讀取,並且是其他人寫的類和記錄部分是真正需要這些的部分...記錄打開串行通信,解析輸入並進一步處理它。 – Lehue

+0

有幾種情況,沒有任何意義,但無論如何你必須這樣做,因爲這是唯一的解決方法,嘗試調用它們以便它們在單個文件中相互依賴,可能是主要的或任何頭文件,爲什麼調用順序重要,讓我們來討論回答 –

+0

這是錯的。如果some1.h需要some.h中的名字,那麼some1.h應該包含some.h。如果源文件需要some.h和some1.h的名字,那麼它應該包含兩個文件。標有「Not Valid:」的代碼非常好,只要some.h有適當的包含警衛。 –

相關問題