C++ 为什么包含语句的顺序如此重要?
在我的程序(wxWidgets,code::blocks)中,我注意到一些我不太理解的行为。如果我这样写标题:C++ 为什么包含语句的顺序如此重要?,c++,wxwidgets,C++,Wxwidgets,在我的程序(wxWidgets,code::blocks)中,我注意到一些我不太理解的行为。如果我这样写标题: #ifndef RECORDTHREAD_H #define RECORDTHREAD_H #include <wx/thread.h> #include <wx/dialog.h> #include <wx/string.h> #include "Serial.h" class RecordTrackDialog; class Record
#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
#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)) ===|
我会遇到如下错误:
#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
#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++(或WxWigGET)的行为是这样的吗?< /P>
编辑:
Serial.h的包含
#ifndef SERIAL_H
#define SERIAL_H
#include <windows.h>
//#include <wx/msw/winundef.h>
#include <stdio.h> // necessary for sprintf
#include <string>
\ifndef SERIAL\u H
#定义序列号
#包括
//#包括
#包括//sprintf所必需的
#包括
这似乎符合Marco的评论,但我不能包括该部分…正如评论所指出的,这可能是因为
Serial.h
依赖于包含主文件的3wx\xxxx
文件中的定义(RecordThread.h
?)
像这样将它们添加到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>
\ifndef SERIAL\u H
#定义序列号
#包括
#包括
#包括
#包括
//#包括
#包括//sprintf所必需的
#包括
如果要正确执行,您应该在Serial.h
中找出您实际需要的一个(或多个),但是添加所有这些应该可以清除错误
编译预处理器时,通过将指定文件复制到主文件的#include
位置,处理#include
。这是一个递归过程,文件可以#包含#包含
文件的文件,等等
对于新手来说,#include
和预处理器似乎有很多神秘主义。它实际上只是一个文本处理工具
在现代C语言的许多地方,在使用之前必须声明(引入/定义)一个符号/标识符。如果在头文件中声明了该符号/标识符,则在使用该文件之前,您应该#包括该文件。仅需遵循一些常见做法,这可能无法回答您的问题,但会为您指出正确的方向:
- 始终让您不要在同一个文件中包含相同的头文件,这意味着混淆,但请使用下图理解它:
有效:
-#include "some.h"
-#include "some1.h"
-#include "some.h"
--#include "some1.h"
-#include "some.h"
-#include "some1.h"
--#include "some.h"
有效:
-#include "some.h"
-#include "some1.h"
-#include "some.h"
--#include "some1.h"
-#include "some.h"
-#include "some1.h"
--#include "some.h"
无效:
-#include "some.h"
-#include "some1.h"
-#include "some.h"
--#include "some1.h"
-#include "some.h"
-#include "some1.h"
--#include "some.h"
因此,除非你知道自己在做什么,否则不要筑巢
您的问题的一个可能解决方案是在Serial.h
中包含wx\thread.h
,wx\dialog.h
,wx\string.h
,请尝试一下,然后告诉我
为什么调用#按顺序包含
因为只有当你理解这样的事情时,这才有意义,阿里需要清洁修理他的车,阿里不知道如何修理他的车,所以阿里会打电话给机械师修理,所以这里我们可以说(阿里依赖机械师):
- #include "mechanic.h"
- #include "Ali.h"
问题在于
根据是否定义了UNICODE
standard(即Windows下的)宏定义了不同的符号。如果首先包含wxWidgets头,默认情况下采用Unicode构建,那么在包含
之前,它们会为您定义Unicode
,一切都很好
如果先包含
,则此时未定义UNICODE
,但当稍后包含wxWidgets头时,它们使用wxUSE_UNICODE=1
(这也是默认值),从而导致您观察到的编译问题
确保不会出现此类问题的最简单方法是在项目设置或makefile中全局定义UNICODE
。什么是Serial.h
?当您使用双引号时,它应该意味着它是您项目中的一个文件-如果您自己的头依赖于其他头,那么您编写的Serial.h
不正确Serial.h
应负责其自身的包含。可能相关:Show us Serial.h。这意味着一个或多个标题被破坏。顺序在正确编写的代码中并不重要。这意味着Serial.h
中的某些内容取决于一个或多个wx
标题中的声明或定义。Serial.h
需要包含它所依赖的那些头文件,或者您总是需要确保包含“Serial.h”的其他文件只有在包含wx
头文件之后才这样做。我理解您的意思,但是从这些类中的每一个来看,将这些头包含在Serial.h
中没有多大意义,因为Serial只是打开并从串行通信读取,是其他人编写的类,而记录部分才是真正需要这些的部分…记录打开串行通信,解析输入并进一步处理。有几种情况下,没有任何意义,但您必须这样做,因为这是唯一的解决方法,请尝试按顺序调用它们,它们在单个文件中相互依赖,可能是主文件或任何头文件,为什么按顺序调用很重要,让我们在回答中讨论这是错误的。如果some1.h需要some.h的名称,那么some1.h应该包含some.h。如果源文件需要来自some.h和some1.h的名称,那么它应该同时包含这两个文件。标记为“无效:”的代码是完全正确的,只要一些.h有适当的include guards。@PeteBecker最好不要把初学者和guards
东西混淆,最好的做法是尽量不要使用它们,我错了吗?你完全错了。包括警卫是C和C++编程的基本工具。不使用它们会导致神秘的相互依赖、顺序依赖和混乱的错误消息。