- Using the Windows Headers
- Visual C++ and the Windows Header Files
- Macros for Conditional Declarations
- Setting WINVER or _WIN32_WINNT
- Controlling Structure Packing
- Faster Builds with Smaller Header Files
- HttpAddRequestHeadersA function (wininet.h)
- Syntax
- Parameters
- Return value
- Remarks
- HttpAddRequestHeadersA function (wininet.h)
- Syntax
- Parameters
- Return value
- Remarks
- Файлы заголовков (C++) Header files (C++)
- Пример Example
- Включить условия Include guards
- Что следует разместить в файле заголовка What to put in a header file
- Пример файла заголовка Sample header file
Using the Windows Headers
The header files for the Windows API enable you to create 32- and 64-bit applications. They include declarations for both Unicode and ANSI versions of the API. For more information, see Unicode in the Windows API. They use data types that enable you to build both 32- and 64-bit versions of your application from a single source code base. For more information, see Getting Ready for 64-bit Windows. Additional features include Header Annotations and STRICT Type Checking.
Visual C++ and the Windows Header Files
Microsoft Visual C++ includes copies of the Windows header files that were current at the time Visual C++ was released. Therefore, if you install updated header files from an SDK, you may end up with multiple versions of the Windows header files on your computer. If you do not ensure that you are using the latest version of the SDK header files, you will receive the following error code when compiling code that uses features that were introduced after Visual C++ was released: error C2065: undeclared identifier.
Macros for Conditional Declarations
Certain functions that depend on a particular version of Windows are declared using conditional code. This enables you to use the compiler to detect whether your application uses functions that are not supported on its target version(s) of Windows. To compile an application that uses these functions, you must define the appropriate macros. Otherwise, you will receive the C2065 error message.
The Windows header files use macros to indicate which versions of Windows support many programming elements. Therefore, you must define these macros to use new functionality introduced in each major operating system release. (Individual header files may use different macros; therefore, if compilation problems occur, check the header file that contains the definition for conditional definitions.) For more information, see SdkDdkVer.h.
The following table describes the preferred macros used in the Windows header files. If you define NTDDI_VERSION, you must also define _WIN32_WINNT.
Minimum system required | Value for NTDDI_VERSION |
---|---|
Windows 10 1903 «19H1» | NTDDI_WIN10_19H1 (0x0A000007) |
Windows 10 1809 «Redstone 5» | NTDDI_WIN10_RS5 (0x0A000006) |
Windows 10 1803 «Redstone 4» | NTDDI_WIN10_RS4 (0x0A000005) |
Windows 10 1709 «Redstone 3» | NTDDI_WIN10_RS3 (0x0A000004) |
Windows 10 1703 «Redstone 2» | NTDDI_WIN10_RS2 (0x0A000003) |
Windows 10 1607 «Redstone 1» | NTDDI_WIN10_RS1 (0x0A000002) |
Windows 10 1511 «Threshold 2» | NTDDI_WIN10_TH2 (0x0A000001) |
Windows 10 1507 «Threshold» | NTDDI_WIN10 (0x0A000000) |
WindowsВ 8.1 | NTDDI_WINBLUE (0x06030000) |
WindowsВ 8 | NTDDI_WIN8 (0x06020000) |
WindowsВ 7 | NTDDI_WIN7 (0x06010000) |
Windows ServerВ 2008 | NTDDI_WS08 (0x06000100) |
WindowsВ Vista with Service PackВ 1 (SP1) | NTDDI_VISTASP1 (0x06000100) |
WindowsВ Vista | NTDDI_VISTA (0x06000000) |
Windows ServerВ 2003 with Service PackВ 2 (SP2) | NTDDI_WS03SP2 (0x05020200) |
Windows ServerВ 2003 with Service PackВ 1 (SP1) | NTDDI_WS03SP1 (0x05020100) |
Windows ServerВ 2003 | NTDDI_WS03 (0x05020000) |
WindowsВ XP with Service PackВ 3 (SP3) | NTDDI_WINXPSP3 (0x05010300) |
WindowsВ XP with Service PackВ 2 (SP2) | NTDDI_WINXPSP2 (0x05010200) |
WindowsВ XP with Service PackВ 1 (SP1) | NTDDI_WINXPSP1 (0x05010100) |
WindowsВ XP | NTDDI_WINXP (0x05010000) |
The following tables describe other macros used in the Windows header files.
Minimum system required | Minimum value for _WIN32_WINNT and WINVER |
---|---|
WindowsВ 10 | _WIN32_WINNT_WIN10 (0x0A00) |
WindowsВ 8.1 | _WIN32_WINNT_WINBLUE (0x0603) |
WindowsВ 8 | _WIN32_WINNT_WIN8 (0x0602) |
WindowsВ 7 | _WIN32_WINNT_WIN7 (0x0601) |
Windows ServerВ 2008 | _WIN32_WINNT_WS08 (0x0600) |
WindowsВ Vista | _WIN32_WINNT_VISTA (0x0600) |
Windows ServerВ 2003 with SP1, WindowsВ XP with SP2 | _WIN32_WINNT_WS03 (0x0502) |
Windows ServerВ 2003, WindowsВ XP | _WIN32_WINNT_WINXP (0x0501) |
Minimum version required | Minimum value of _WIN32_IE |
---|---|
Internet Explorer 11.0 | _WIN32_IE_IE110 (0x0A00) |
Internet Explorer 10.0 | _WIN32_IE_IE100 (0x0A00) |
Internet Explorer 9.0 | _WIN32_IE_IE90 (0x0900) |
Internet Explorer 8.0 | _WIN32_IE_IE80 (0x0800) |
Internet Explorer 7.0 | _WIN32_IE_IE70 (0x0700) |
Internet Explorer 6.0 SP2 | _WIN32_IE_IE60SP2 (0x0603) |
Internet Explorer 6.0 SP1 | _WIN32_IE_IE60SP1 (0x0601) |
Internet Explorer 6.0 | _WIN32_IE_IE60 (0x0600) |
Internet Explorer 5.5 | _WIN32_IE_IE55 (0x0550) |
Internet Explorer 5.01 | _WIN32_IE_IE501 (0x0501) |
Internet Explorer 5.0, 5.0a, 5.0b | _WIN32_IE_IE50 (0x0500) |
Setting WINVER or _WIN32_WINNT
You can define these symbols by using the #define statement in each source file, or by specifying the /D compiler option supported by Visual C++.
For example, to set WINVER in your source file, use the following statement:
#define WINVER 0x0502
To set _WIN32_WINNT in your source file, use the following statement:
#define _WIN32_WINNT 0x0502
To set _WIN32_WINNT using the /D compiler option, use the following command:
cl -c /D_WIN32_WINNT=0x0502 source.cpp
For information on using the /D compiler option, see /D (preprocessor definitions).
Note that some features introduced in the latest version of Windows may be added to a service pack for a previous version of Windows. Therefore, to target a service pack, you may need to define _WIN32_WINNT with the value for the next major operating system release. For example, the GetDllDirectory function was introduced in Windows ServerВ 2003 and is conditionally defined if _WIN32_WINNT is 0x0502 or greater. This function was also added to WindowsВ XP with SP1. Therefore, if you were to define _WIN32_WINNT as 0x0501 to target WindowsВ XP, you would miss features that are defined in WindowsВ XP with SP1.
Controlling Structure Packing
Projects should be compiled to use the default structure packing, which is currently 8 bytes because the largest integral type is 8 bytes. Doing so ensures that all structure types within the header files are compiled into the application with the same alignment the Windows API expects. It also ensures that structures with 8-byte values are properly aligned and will not cause alignment faults on processors that enforce data alignment.
Faster Builds with Smaller Header Files
You can reduce the size of the Windows header files by excluding some of the less common API declarations as follows:
Define WIN32_LEAN_AND_MEAN to exclude APIs such as Cryptography, DDE, RPC, Shell, and Windows Sockets.
HttpAddRequestHeadersA function (wininet.h)
Adds one or more HTTP request headers to the HTTP request handle.
Syntax
Parameters
A handle returned by a call to the HttpOpenRequest function.
A pointer to a string variable containing the headers to append to the request. Each header must be terminated by a CR/LF (carriage return/line feed) pair.
The size of lpszHeaders, in TCHARs. If this parameter is -1L, the function assumes that lpszHeaders is zero-terminated (ASCIIZ), and the length is computed.
A set of modifiers that control the semantics of this function. This parameter can be a combination of the following values.
Value | Meaning |
---|---|
HTTP_ADDREQ_FLAG_ADD | Adds the header if it does not exist. Used with HTTP_ADDREQ_FLAG_REPLACE. |
HTTP_ADDREQ_FLAG_ADD_IF_NEW | Adds the header only if it does not already exist; otherwise, an error is returned. |
HTTP_ADDREQ_FLAG_COALESCE | Coalesces headers of the same name. |
HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA | Coalesces headers of the same name. For example, adding «Accept: text/*» followed by «Accept: audio/*» with this flag results in the formation of the single header «Accept: text/*, audio/*». This causes the first header found to be coalesced. It is up to the calling application to ensure a cohesive scheme with respect to coalesced/separate headers. |
HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON | Coalesces headers of the same name using a semicolon. |
HTTP_ADDREQ_FLAG_REPLACE | Replaces or removes a header. If the header value is empty and the header is found, it is removed. If not empty, the header value is replaced. |
Return value
Returns TRUE if successful, or FALSE otherwise. To get extended error information, call GetLastError.
Remarks
HttpAddRequestHeaders appends additional, free-format headers to the HTTP request handle and is intended for use by sophisticated clients that need detailed control over the exact request sent to the HTTP server.
Note that for basic HttpAddRequestHeaders, the application can pass in multiple headers in a single buffer. If the application is trying to remove or replace a header, only one header can be supplied in lpszHeaders.
The wininet.h header defines HttpAddRequestHeaders as an alias which automatically selects the ANSI or Unicode version of this function based on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for Function Prototypes.
HttpAddRequestHeadersA function (wininet.h)
Adds one or more HTTP request headers to the HTTP request handle.
Syntax
Parameters
A handle returned by a call to the HttpOpenRequest function.
A pointer to a string variable containing the headers to append to the request. Each header must be terminated by a CR/LF (carriage return/line feed) pair.
The size of lpszHeaders, in TCHARs. If this parameter is -1L, the function assumes that lpszHeaders is zero-terminated (ASCIIZ), and the length is computed.
A set of modifiers that control the semantics of this function. This parameter can be a combination of the following values.
Value | Meaning |
---|---|
HTTP_ADDREQ_FLAG_ADD | Adds the header if it does not exist. Used with HTTP_ADDREQ_FLAG_REPLACE. |
HTTP_ADDREQ_FLAG_ADD_IF_NEW | Adds the header only if it does not already exist; otherwise, an error is returned. |
HTTP_ADDREQ_FLAG_COALESCE | Coalesces headers of the same name. |
HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA | Coalesces headers of the same name. For example, adding «Accept: text/*» followed by «Accept: audio/*» with this flag results in the formation of the single header «Accept: text/*, audio/*». This causes the first header found to be coalesced. It is up to the calling application to ensure a cohesive scheme with respect to coalesced/separate headers. |
HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON | Coalesces headers of the same name using a semicolon. |
HTTP_ADDREQ_FLAG_REPLACE | Replaces or removes a header. If the header value is empty and the header is found, it is removed. If not empty, the header value is replaced. |
Return value
Returns TRUE if successful, or FALSE otherwise. To get extended error information, call GetLastError.
Remarks
HttpAddRequestHeaders appends additional, free-format headers to the HTTP request handle and is intended for use by sophisticated clients that need detailed control over the exact request sent to the HTTP server.
Note that for basic HttpAddRequestHeaders, the application can pass in multiple headers in a single buffer. If the application is trying to remove or replace a header, only one header can be supplied in lpszHeaders.
The wininet.h header defines HttpAddRequestHeaders as an alias which automatically selects the ANSI or Unicode version of this function based on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for Function Prototypes.
Файлы заголовков (C++) Header files (C++)
Имена программных элементов, таких как переменные, функции, классы и т. д., должны быть объявлены, прежде чем их можно будет использовать. The names of program elements such as variables, functions, classes, and so on must be declared before they can be used. Например, нельзя просто писать x = 42 без предварительного объявления «x». For example, you can’t just write x = 42 without first declaring ‘x’.
Объявление сообщает компилятору, является ли элемент int , a double , функцией class или другим элементом. The declaration tells the compiler whether the element is an int , a double , a function, a class or some other thing. Кроме того, каждое имя должно быть объявлено (прямо или косвенно) в каждом cpp-файле, в котором он используется. Furthermore, each name must be declared (directly or indirectly) in every .cpp file in which it is used. При компиляции программы каждый CPP-файл компилируется независимо в единицу компиляции. When you compile a program, each .cpp file is compiled independently into a compilation unit. Компилятор не имеет сведений о том, какие имена объявляются в других единицах компиляции. The compiler has no knowledge of what names are declared in other compilation units. Это означает, что если вы определите класс или функцию или глобальную переменную, необходимо предоставить объявление этого объекта в каждом дополнительном cpp-файле, который его использует. That means that if you define a class or function or global variable, you must provide a declaration of that thing in each additional .cpp file that uses it. Каждое объявление этого элемента должно быть точно одинаковым во всех файлах. Each declaration of that thing must be exactly identical in all files. Небольшая несогласованность вызовет ошибки или непреднамеренное поведение, когда компоновщик пытается объединить все единицы компиляции в одну программу. A slight inconsistency will cause errors, or unintended behavior, when the linker attempts to merge all the compilation units into a single program.
Чтобы максимально сокращать возможности ошибок, в C++ принято соглашение об использовании файлов заголовков для хранения объявлений. To minimize the potential for errors, C++ has adopted the convention of using header files to contain declarations. Объявления можно сделать в файле заголовка, а затем использовать директиву #include в каждом cpp-файле или другом файле заголовка, для которого требуется это объявление. You make the declarations in a header file, then use the #include directive in every .cpp file or other header file that requires that declaration. Директива #include вставляет копию файла заголовка непосредственно в CPP-файл перед компиляцией. The #include directive inserts a copy of the header file directly into the .cpp file prior to compilation.
В Visual Studio 2019 функция модулей c++ 20 появилась в качестве улучшения и в конечном итоге заменяет файлы заголовков. In Visual Studio 2019, the C++20 modules feature is introduced as an improvement and eventual replacement for header files. Дополнительные сведения см. в разделе Общие сведения о модулях в C++. For more information, see Overview of modules in C++.
Пример Example
В следующем примере показан общий способ объявления класса и его использования в другом исходном файле. The following example shows a common way to declare a class and then use it in a different source file. Начнем с файла заголовка, my_class.h . We’ll start with the header file, my_class.h . Он содержит определение класса, но обратите внимание, что определение не завершено; Функция-член do_something не определена: It contains a class definition, but note that the definition is incomplete; the member function do_something is not defined:
Затем создайте файл реализации (обычно с расширением CPP или аналогичным модулем). Next, create an implementation file (typically with a .cpp or similar extension). Мы вызываем файл my_class. cpp и предоставим определение для объявления члена. We’ll call the file my_class.cpp and provide a definition for the member declaration. Мы добавляем #include директиву для файла «my_class. h», чтобы объявление my_class, вставленное в этот момент в cpp, было включено в объявление для std::cout . We add an #include directive for «my_class.h» file in order to have the my_class declaration inserted at this point in the .cpp file, and we include to pull in the declaration for std::cout . Обратите внимание, что кавычки используются для файлов заголовков в том же каталоге, что и исходный файл, а угловые скобки используются для заголовков стандартной библиотеки. Note that quotes are used for header files in the same directory as the source file, and angle brackets are used for standard library headers. Кроме того, многие заголовки стандартной библиотеки не имеют h или любого другого расширения файла. Also, many standard library headers do not have .h or any other file extension.
В файле реализации при необходимости можно использовать using оператор, чтобы не указывать каждое упоминание «my_class» или «cout» с «N::» или «std::». In the implementation file, we can optionally use a using statement to avoid having to qualify every mention of «my_class» or «cout» with «N::» or «std::». Не помещайте using операторы в файлы заголовков! Don’t put using statements in your header files!
Теперь можно использовать my_class в другом cpp файле. Now we can use my_class in another .cpp file. Мы #include заголовочный файл, чтобы компилятор запрашивает объявление. We #include the header file so that the compiler pulls in the declaration. Все компиляторы должны иметь представление о том, что my_class — это класс, имеющий открытую функцию-член с именем do_something() . All the compiler needs to know is that my_class is a class that has a public member function called do_something() .
После того как компилятор завершит компиляцию каждого CPP-файла в OBJ-файлы, он передает OBJ-файлы компоновщику. After the compiler finishes compiling each .cpp file into .obj files, it passes the .obj files to the linker. Когда компоновщик объединяет объектные файлы, обнаруживается только одно определение для my_class; Он находится в OBJ-файле, созданном для my_class. cpp, и сборка выполняется. When the linker merges the object files it finds exactly one definition for my_class; it is in the .obj file produced for my_class.cpp, and the build succeeds.
Включить условия Include guards
Как правило, файлы заголовков содержат директиву include или, #pragma once чтобы убедиться, что они не вставляются несколько раз в один CPP-файл. Typically, header files have an include guard or a #pragma once directive to ensure that they are not inserted multiple times into a single .cpp file.
Что следует разместить в файле заголовка What to put in a header file
Поскольку файл заголовка потенциально может включаться в несколько файлов, он не может содержать определения, которые могут формировать несколько определений с одним и тем же именем. Because a header file might potentially be included by multiple files, it cannot contain definitions that might produce multiple definitions of the same name. Следующие действия не разрешены или считаются очень неправильными. The following are not allowed, or are considered very bad practice:
- встроенные определения типов в пространстве имен или глобальной области built-in type definitions at namespace or global scope
- невстроенные определения функций non-inline function definitions
- определения неконстантных переменных non-const variable definitions
- агрегатные определения aggregate definitions
- безымянные пространства имен unnamed namespaces
- Директивы using using directives
Использование using директивы не обязательно приведет к ошибке, но может вызвать проблему, так как она переводит пространство имен в область каждого CPP-файла, который напрямую или косвенно включает этот заголовок. Use of the using directive will not necessarily cause an error, but can potentially cause a problem because it brings the namespace into scope in every .cpp file that directly or indirectly includes that header.
Пример файла заголовка Sample header file
В следующем примере показаны различные виды объявлений и определений, допустимых в файле заголовка. The following example shows the various kinds of declarations and definitions that are allowed in a header file: