乘风破浪,遇见最美Windows 11之现代Windows桌面应用开发 - 使用C++创建Windows桌面应用程序
什么是C++中的Windows桌面应用程序
https://learn.microsoft.com/zh-cn/cpp/windows/desktop-applications-visual-cpp
用C++编写的桌面应用程序是一个本地应用程序,它可以访问全套的Windows API,并在窗口或系统控制台中运行。用C++编写的桌面应用程序可以在Windows XP到Windows 11上运行(尽管Windows XP已不再得到官方支持,而且有许多Windows API是在那之后引入的)。
桌面应用程序与通用Windows平台(UWP)应用程序不同,后者可以在运行Windows 11、Windows 10、XBox、Windows Phone、Surface Hub和其他设备的PC上运行。
什么是Windows API
https://docs.microsoft.com/zh-cn/cpp/windows/walkthrough-creating-windows-desktop-applications-cpp
Windows API(也被称为Win32 API、Windows桌面API和Windows经典API)是一个基于C语言的框架,用于创建Windows应用程序。它自20世纪80年代以来一直存在,几十年来一直被用来创建Windows应用程序。更高级和更容易编程的框架已经建立在Windows API之上,例如,MFC、ATL、.NET框架。 即使是用C++/WinRT编写的UWP和Store应用程序的最现代的Windows Runtime代码也使用Windows API的底层。
先决条件
-
一台运行微软Windows 7或更高版本的计算机。我们建议使用Windows 10或更高版本以获得最佳的开发体验。
-
一份Visual Studio的拷贝。关于如何下载和安装Visual Studio的信息,请参见安装Visual Studio。当你运行安装程序时,确保勾选了用C++进行桌面开发(Desktop development with C++) 的工作负载。如果你在安装Visual Studio时没有安装这个工作负载,不要担心。你可以再次运行安装程序,现在就安装它。
Visual Studio安装程序中使用C++的桌面开发工作负载的细节。
-
了解使用Visual Studio IDE的基本知识。如果你以前使用过Windows桌面应用程序,你可能可以跟上。有关介绍,请参见Visual Studio IDE功能之旅。
-
对C++语言的基础知识有足够的了解,可以跟着学。别担心,我们不会做太复杂的事情。
创建一个Windows桌面项目
按照这些步骤来创建你的第一个Windows桌面项目。在你进行的过程中,你将为一个工作的Windows桌面应用程序输入代码。要查看你喜欢的Visual Studio版本的文档,请使用版本选择器控件。它位于本页面目录的顶部
要在Visual Studio中创建一个Windows桌面项目
- 在主菜单中,选择"文件(File)">"新建(New)">"项目(Project)",打开"创建新项目(Create a New Project)"的对话框。
- 在对话框的顶部,将"语言(Language)"设置为"C++",将"平台(Platform)"设置为"Windows",并将"项目类型(Project type)"设置为"桌面(Desktop)"。
- 从过滤后的项目类型列表中,选择"Windows桌面向导(Windows Desktop Wizard)",然后选择"下一步(Next)"。在下一页,为项目输入一个名称,例如,"DemoForCppDesktop"。
- 选择"创建(Create)"按钮来创建项目。
- 现在出现"Windows桌面项目(Windows Desktop Project)"对话框。在"应用程序类型(Application type)"下,选择"桌面应用程序(Desktop application)(.exe)"。在"其他选项(Additional options)"下,选择"空项目(Empty project)"。选择"确定(OK)"来创建这个项目。
- 在"解决方案资源管理器(Solution Explorer)"中,右键单击"DemoForCppDesktop"项目,选择"添加(Add)",然后选择"新建项(New Item)"。
- 在"添加新项(Add New Item)"对话框中,选择"C++文件(C++ File)(.cpp)"。在"名称(Name)"框中,键入一个文件名,例如,
HelloWindowsDesktop.cpp
。选择"添加(Add)"。
现在你的项目已经创建,你的源文件在编辑器中被打开。要继续,请跳到创建代码。
创建代码
接下来,你将学习如何在Visual Studio中创建一个Windows桌面应用程序的代码。
要启动一个Windows桌面应用程序
- 就像每个C语言程序和C++程序都必须有一个main函数作为其起点一样,每个Windows桌面程序都必须有一个WinMain函数。WinMain的语法如下。
int WINAPI WinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
);
有关该函数的参数和返回值的信息,见WinMain入口点。
所有这些额外的词,如
WINAPI
,或CALLBACK
,或HINSTANCE
,或_In_
,都是什么?传统的Windows API广泛使用类型化定义和预处理器宏来抽象出类型和平台特定代码的一些细节,如调用约定、__declspec
声明和编译器语义。在Visual Studio中,你可以使用IntelliSense快速信息功能来查看这些类型定义和宏的定义。将鼠标悬停在感兴趣的词上,或者选择它并按下Ctrl
+K
、Ctrl
+I
,就会弹出一个包含定义的小窗口。欲了解更多信息,请参见使用智能提示。参数和返回类型经常使用SAL注释来帮助你发现编程错误。欲了解更多信息,请参阅使用SAL注释来减少C/C++代码缺陷。
- Windows桌面程序需要
<windows.h>
.<tchar.h>
定义了TCHAR
宏,如果你的项目中定义了UNICODE
符号,它最终会解析为wchar_t
,否则会解析为char
。如果你总是在启用UNICODE
的情况下构建,你就不需要TCHAR
,可以直接使用wchar_t
。
#include <windows.h>
#include <tchar.h>
- 除了
WinMain
函数外,每个Windows桌面应用程序还必须有一个窗口程序函数。这个函数通常被命名为WndProc
,但你可以随心所欲地命名它。WndProc
的语法如下。
LRESULT CALLBACK WndProc(
_In_ HWND hWnd,
_In_ UINT message,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
在这个函数中,你写代码来处理事件发生时应用程序从Windows收到的消息。例如,如果用户在你的应用程序中选择了一个OK按钮,Windows将向你发送一条消息,你可以在WndProc
函数中编写代码,做任何适当的工作。这就是所谓的处理一个事件。你只处理与你的应用程序有关的事件。
欲了解更多信息,请参见窗口程序。
为了给WinMain函数增加功能
- 在
WinMain
函数中,你填充了一个WNDCLASSEX
类型的结构。该结构包含关于窗口的信息:应用程序的图标、窗口的背景颜色、显示在标题栏中的名称,以及其他一些东西。重要的是,它包含一个指向你的窗口程序的函数指针。下面的例子显示了一个典型的WNDCLASSEX
结构。
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(wcex.hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
关于上述结构的字段信息,见WNDCLASSEX。
- 向Windows注册
WNDCLASSEX
,这样它就知道你的窗口以及如何向它发送消息。使用RegisterClassEx
函数,并将窗口类结构作为参数传递。使用_T
宏,因为我们使用TCHAR
类型。
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
- 现在你可以创建一个窗口。使用
CreateWindowEx
函数。
static TCHAR szWindowClass[] = _T("DesktopApp");
static TCHAR szTitle[] = _T("Windows Desktop Guided Tour Application");
// The parameters to CreateWindowEx explained:
// WS_EX_OVERLAPPEDWINDOW : An optional extended window style.
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindowEx(
WS_EX_OVERLAPPEDWINDOW,
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 100,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindowEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
这个函数返回一个HWND
,它是一个窗口的句柄。一个句柄有点像一个指针,Windows用它来跟踪打开的窗口。欲了解更多信息,请参见Windows数据类型。
- 在这一点上,窗口已经被创建,但我们仍然需要告诉Windows使其可见。这就是这段代码的作用:
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
显示的窗口没有什么内容,因为你还没有实现WndProc
函数。换句话说,应用程序还没有处理Windows现在向它发送的信息。
- 为了处理这些消息,我们首先添加一个消息循环来监听Windows发送的消息。当应用程序收到一个消息时,这个循环将其分派给你的
WndProc
函数来处理。该消息循环类似于以下代码。
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
关于消息循环中的结构和函数的更多信息,请参见MSG, GetMessage, TranslateMessage, 和DispatchMessage。
在这一点上,WinMain
函数应该类似于以下代码。
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(wcex.hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// Store instance handle in our global variable
hInst = hInstance;
// The parameters to CreateWindowEx explained:
// WS_EX_OVERLAPPEDWINDOW : An optional extended window style.
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application dows not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindowEx(
WS_EX_OVERLAPPEDWINDOW,
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 100,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
为了给WndProc函数增加功能
- 为了使
WndProc
函数能够处理应用程序收到的消息,实现一个switch语句。
要处理的一个重要消息是WM_PAINT
消息。当其显示的窗口的一部分必须被更新时,应用程序就会收到WM_PAINT
消息。当用户把一个窗口移到你的窗口前面,然后又把它移开,这个事件就会发生。你的应用程序不知道这些事件何时发生。只有Windows知道,所以它用WM_PAINT
消息来通知你的应用程序。当窗口第一次被显示时,所有的窗口都必须被更新。
要处理一个WM_PAINT
消息,首先要调用BeginPaint
,然后处理所有的逻辑来布置窗口中的文本、按钮和其他控件,然后调用EndPaint
。对于应用程序来说,在开始调用和结束调用之间的逻辑在窗口中显示字符串 "你好,Windows桌面!"。在下面的代码中,TextOut
函数被用来显示这个字符串。
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Hello, Windows desktop!");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Here your application is laid out.
// For this introduction, we just print out "Hello, Windows desktop!"
// in the top left corner.
TextOut(hdc,
5, 5,
greeting, _tcslen(greeting));
// End application-specific layout section.
EndPaint(hWnd, &ps);
break;
}
代码中的HDC
是一个设备上下文的句柄,用于在窗口的客户区绘图。使用BeginPaint
和EndPaint
函数来准备和完成客户端区域的绘制。BeginPaint
返回用于在客户端区域绘图的显示设备上下文的句柄;EndPaint
结束绘图请求并释放设备上下文。
- 一个应用程序通常会处理许多其他的消息。例如,当一个窗口第一次被创建时,
WM_CREATE
,当窗口关闭时,WM_DESTROY
。下面的代码显示了一个基本但完整的WndProc
函数。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Hello, Windows desktop!");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Here your application is laid out.
// For this introduction, we just print out "Hello, Windows desktop!"
// in the top left corner.
TextOut(hdc,
5, 5,
greeting, _tcslen(greeting));
// End application specific layout section.
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
构建代码
正如承诺的那样,这里是工作程序的完整代码。
要建立这个例子
- 在编辑器中删除你在
HelloWindowsDesktop.cpp
中输入的任何代码。复制此示例代码,然后将其粘贴到HelloWindowsDesktop.cpp
中。
// HelloWindowsDesktop.cpp
// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
// Global variables
// The main window class name.
static TCHAR szWindowClass[] = _T("DesktopApp");
// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("Windows Desktop Guided Tour Application");
// Stored instance handle for use in Win32 API calls such as FindResource
HINSTANCE hInst;
// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(wcex.hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// Store instance handle in our global variable
hInst = hInstance;
// The parameters to CreateWindowEx explained:
// WS_EX_OVERLAPPEDWINDOW : An optional extended window style.
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindowEx(
WS_EX_OVERLAPPEDWINDOW,
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 100,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Hello, Windows desktop!");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Here your application is laid out.
// For this introduction, we just print out "Hello, Windows desktop!"
// in the top left corner.
TextOut(hdc,
5, 5,
greeting, _tcslen(greeting));
// End application-specific layout section.
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
- 在"构建(Build)"菜单上,选择"构建解决方案(Build Solution)"。编译的结果应该出现在Visual Studio的"输出(Output)"窗口中。
- 要运行该应用程序,按
F5
。一个包含"Hello, Windows desktop!"文字的窗口应该出现在显示屏的左上角。
恭喜你!你已经完成了本攻略,并建立了一个传统的Windows桌面应用程序。你已经完成了本攻略并建立了一个传统的Windows桌面应用程序。
通过命令行编译本机C++程序
创建Hello.cpp
添加如下内容:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello, world, from Visual C++!" << endl;
}
通过命令行编译Hello.cpp
cl /EHsc Hello.cpp
cl.exe
编译器会生成包含已编译代码的.obj
文件,然后运行链接器来创建名为Hello.exe
的可执行程序
执行编译后的Hello.exe
.\Hello
用C++编写第一个程序
简介
C++旨在支持过程、面向对象的编程和泛型编程。这是一种基于编译器的编程语言,因此经过静态类型化且区分大小写。C++的用法是无限的。
下面是使用C++的一些示例:
-
Web浏览器。C++用于创建Web浏览器及其插件和扩展。
-
操作系统。C++用于构建操作系统。许多版本的Windows部分都是用C++编写的。SymbianOS主要采用C++编写而成。
-
编译器。编译器,因为用于C#和Java等语言的编译器都是用C++编写的。事实上,许多C++编译器都是用C++编写的。
-
媒体应用程序。C++用于创建媒体应用程序并管理音频和视频文件。C++用于实现实时音频的应用程序,如有声读物和转录视频的应用。
-
数据库引擎。C++已用于开发数据库应用程序(包括MySQL)。
-
游戏。多种动画和游戏都需要C++才能进行建模、制作3D动画、渲染和模拟。开发者经常用来创建游戏的游戏引擎可使用C++进行构建。
-
医疗工程。使用医疗工程的开发者将使用C++创建更多的应用程序。C++在使用扫描技术(如MRI)的计算机中广泛使用。C++也用于各种嵌入式系统。
-
机器人。机器人开发者通常会使用C++来对微控制器进行编程,从而提高性能和工作效率。许多硬件库是用C++编写的,以便与低级别硬件进行交互。
创建hello.cpp
在C盘创建CppFirstApp
目录,使用Visual Studio Code打开它,创建一个hello.cpp
文件。
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World!\n";
return 0;
}
在Windows上使用MSVC编译器编译CPP文件
编译器可将用某种语言编写的源代码转换为另一种语言。在这里,编译器将C++源代码转换为计算机代码。计算机理解计算机代码,并创建可执行程序。
找到你的Visual Studio,它有个Developer Command Prompt for VS 2022
,它本质是连接到
%comspec% /k "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat"
我们切换到CppFirstApp
目录,通过如下命令编译
cl hello.cpp
c:\CppFirstApp>cl hello.cpp
用于 x86 的 Microsoft (R) C/C++ 优化编译器 19.35.32215 版
版权所有(C) Microsoft Corporation。保留所有权利。
hello.cpp
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.35.32215\include\ostream(774): warning C4530: 使用了 C++ 异常处理程序,但未启用展开语义。请指定 /EHsc
hello.cpp(5): note: 查看对正在编译的函数 模板 实例化“std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)”的引用
Microsoft (R) Incremental Linker Version 14.35.32215.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:hello.exe
hello.obj
最终我们看到得到了hello.exe
和hello.obj
两个文件。
.\hello.exe
这时候我们直接执行hello.exe
就行了。
修改输出内容
#include <iostream>
using namespace std;
int main()
{
//cout << "Hello World!\n";
cout << "Congratulations!";
cout << " ";
cout << "You wrote your first lines of code in C++.\n";
return 0;
}
重新之前编辑并且运行。
这里编译器的主要工作是将代码转换为计算机可以理解的可执行格式。
C++是区分大小写的。
C++使用双引号创建字符串字面量。
在Linux上使用G++编译器编译CPP文件
g++ hello.cpp && ls
这时候会得到一个a.out
文件。
执行这个文件
./a.out
程序在C++中的工作原理
为了更好地了解上诉内容,从最上面一行开始逐行浏览程序语法很有帮助。
iostream
是标准库的一部分。程序中的许多组件都由标准库,或者你或第三方写入的库定义。代码利用标准库的一部分iostream
来使用cout
对象输出某些内容。
#include <iostream>
namespace
命名空间有助于防止大型项目中的名称冲突。你想要在整个代码中使用命名空间的功能,而无需在需要时重复调用命名空间。因此,在代码的开头声明命名空间。此外,使用cout
所需的语法是std::cout
。添加using namespace std
;行后,无需重复使用std
。
#include <iostream>
using namespace std;
- 函数是共同执行任务的一组语句。
main()
是全局函数,它是程序的指定开头。每个C++程序都必须具有main()
函数。main()
之前使用的int表示此函数需要返回一个整数。
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World\n";
return 0;
}
cout
输出特定字符串。std::cout
是std::ostream
类的数据和操作集合的一部分。
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World\n";
return 0;
}
Hello World
输出设置在双引号("")中。可以通过多种方式使用std::string
。使用std::string
的主要方式有两种,一种是作为C字符串(字符数组),一种是作为string类。char
是基元数据类型。
我们使用不同的数据类型(如整数、单精度浮点数、双精度浮点数和字符)来表示和存储值。例如,整数可能是123,单精度浮点数可能是9.02,字符可能是'a'。
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World\n";
return 0;
}
- 使用
\n
终止字符串,并移到下一行。\n
称为“转义序列”。
cout << "Hello World\n";
除了使用\n
来换行,还可以支持使用endl
操纵器。
cout << "Hello World" << endl;
- 声明函数
int main()
时,指定int
以声明返回整数的函数。如果函数前面有int
,则它要求返回一个整数。因此,编写return 0
后可以确保返回一个整数来完成函数。在这里,return
是关键字,0
是整数。
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World\n";
return 0;
}
常见错误
C++时可能遇到的常见错误的摘要
-
大写字母错误。C++区分大小写,大小写很重要。如果在代码中使用了错误的大小写,则编译器无法识别你尝试使用的命令。
-
流运算符错误。使用正确的运算符非常重要。例如,识别要输出的流或读取信息时。
-
引号类型错误。单个字符需要加单引号。多个字符的字符串字面量和字需要加双引号。
-
缺少分号。所有语句都需要以分号(
;
)结尾。
- 大写字母(如大写
cout
中的c或大写return中的r)会导致错误。使用不正确的大小写会导致编译错误。
Return 0; // 错误
return 0; // 正确
- 使用流运算符将流引导到两个方向中的一个方向-从流中读取(
>>
)或写入流中(<<
)。一个常见错误是使用了错误的流运算符,例如在cout
中使用a >>
而不是a <<
。
cout >> "a string"; // 错误
cout << "a string"; // 正确
- 必须记住是使用单引号还是双引号。使用单引号('')表示单个字符,例如"Hello World"中的'H'。使用双引号("")表示用于形成单词或字符串的多个字符,例如"Hello"或"Hello World"。
cout << 'a string'; // 错误
cout << "a string"; // 正确
- 使用分号标记语句的结尾。如果忘记使用分号,编译器会认为语句在继续。结果通常是编译错误。
cout << "a string" // 错误
cout << 'a string'; // 错误
cout << "a string"; // 正确
修复其中错误的代码
#include (iostream);
using namespace std;
int main()
{
cout >> 'Hello World'
}
- 第一个错误:括号代替了尖括号
hello.cpp:1:10: error: #include expects "FILENAME" or <FILENAME>
1 | #include (iostream);
#include <iostream>;
- 第二个错误:额外的分号
hello.cpp:1:20: warning: extra tokens at end of #include directive
1 | #include <iostream>;
文件名/库iostream的末尾添加了分号;
。不能在#include
指令后添加分号,仅在语句末尾使用分号。
- 第三个错误:字符串字面量的引号类型错误
hello.cpp:5:11: warning: character constant too long for its type
5 | cout >> 'Hello World'
代码使用单引号而不是双引号。仅对单个字符使用单引号。应对字符串字面量(字符数组)使用双引号。
- 第四个错误:流运算符错误
hello.cpp: In function ‘int main()’:
hello.cpp:5:8: error: no match for ‘operator>>’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘const char [12]’)
5 | cout >> "Hello World"
对cout
对象使用<<
。对cin
对象使用>>
- 第五个错误:缺少分号
hello.cpp: In function ‘int main()’:
hello.cpp:5:24: error: expected ‘;’ before ‘}’ token
5 | cout << "Hello World"
语句末尾需要加分号。
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World";
}
- 为什么没有返回不报错
代码末尾不包含return 0
,但未引发任何错误。原因是,运行时假定将隐式返回类型作为main的整数。返回类型主要用于退出状态。在这里,返回0或不返回任何内容都会使运行时假定代码已成功退出。